window.log = function () {
    if (log.history = log.history || [], log.history.push(arguments), this.console) {
        var newarr, args = arguments;
        args.callee = args.callee.caller, newarr = [].slice.call(args), "object" == typeof console.log ? log.apply.call(console.log, console, newarr) : console.log.apply(console, newarr)
    }
},
function (a) {
    function b() {}
    for (var d, c = "assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(","); d = c.pop();) a[d] = a[d] || b
}(function () {
    try {
        return console.log(), window.console
    } catch (a) {
        return window.console = {}
    }
}()),
function (e, t) {
    function i(t, n) {
        var r, i, o, u = t.nodeName.toLowerCase();
        return "area" === u ? (r = t.parentNode, i = r.name, t.href && i && "map" === r.nodeName.toLowerCase() ? (o = e("img[usemap=#" + i + "]")[0], !!o && s(o)) : !1) : (/input|select|textarea|button|object/.test(u) ? !t.disabled : "a" === u ? t.href || n : n) && s(t)
    }

    function s(t) {
        return e.expr.filters.visible(t) && !e(t).parents().addBack().filter(function () {
            return "hidden" === e.css(this, "visibility")
        }).length
    }
    var n = 0,
        r = /^ui-id-\d+$/;
    e.ui = e.ui || {}, e.ui.version || (e.extend(e.ui, {
        version: "1.10.1",
        keyCode: {
            BACKSPACE: 8,
            COMMA: 188,
            DELETE: 46,
            DOWN: 40,
            END: 35,
            ENTER: 13,
            ESCAPE: 27,
            HOME: 36,
            LEFT: 37,
            NUMPAD_ADD: 107,
            NUMPAD_DECIMAL: 110,
            NUMPAD_DIVIDE: 111,
            NUMPAD_ENTER: 108,
            NUMPAD_MULTIPLY: 106,
            NUMPAD_SUBTRACT: 109,
            PAGE_DOWN: 34,
            PAGE_UP: 33,
            PERIOD: 190,
            RIGHT: 39,
            SPACE: 32,
            TAB: 9,
            UP: 38
        }
    }), e.fn.extend({
        _focus: e.fn.focus,
        focus: function (t, n) {
            return "number" == typeof t ? this.each(function () {
                var r = this;
                setTimeout(function () {
                    e(r).focus(), n && n.call(r)
                }, t)
            }) : this._focus.apply(this, arguments)
        },
        scrollParent: function () {
            var t;
            return t = e.ui.ie && /(static|relative)/.test(this.css("position")) || /absolute/.test(this.css("position")) ? this.parents().filter(function () {
                return /(relative|absolute|fixed)/.test(e.css(this, "position")) && /(auto|scroll)/.test(e.css(this, "overflow") + e.css(this, "overflow-y") + e.css(this, "overflow-x"))
            }).eq(0) : this.parents().filter(function () {
                return /(auto|scroll)/.test(e.css(this, "overflow") + e.css(this, "overflow-y") + e.css(this, "overflow-x"))
            }).eq(0), /fixed/.test(this.css("position")) || !t.length ? e(document) : t
        },
        zIndex: function (n) {
            if (n !== t) return this.css("zIndex", n);
            if (this.length)
                for (var i, s, r = e(this[0]); r.length && r[0] !== document;) {
                    if (i = r.css("position"), ("absolute" === i || "relative" === i || "fixed" === i) && (s = parseInt(r.css("zIndex"), 10), !isNaN(s) && 0 !== s)) return s;
                    r = r.parent()
                }
            return 0
        },
        uniqueId: function () {
            return this.each(function () {
                this.id || (this.id = "ui-id-" + ++n)
            })
        },
        removeUniqueId: function () {
            return this.each(function () {
                r.test(this.id) && e(this).removeAttr("id")
            })
        }
    }), e.extend(e.expr[":"], {
        data: e.expr.createPseudo ? e.expr.createPseudo(function (t) {
            return function (n) {
                return !!e.data(n, t)
            }
        }) : function (t, n, r) {
            return !!e.data(t, r[3])
        },
        focusable: function (t) {
            return i(t, !isNaN(e.attr(t, "tabindex")))
        },
        tabbable: function (t) {
            var n = e.attr(t, "tabindex"),
                r = isNaN(n);
            return (r || n >= 0) && i(t, !r)
        }
    }), e("<a>").outerWidth(1).jquery || e.each(["Width", "Height"], function (n, r) {
        function u(t, n, r, s) {
            return e.each(i, function () {
                n -= parseFloat(e.css(t, "padding" + this)) || 0, r && (n -= parseFloat(e.css(t, "border" + this + "Width")) || 0), s && (n -= parseFloat(e.css(t, "margin" + this)) || 0)
            }), n
        }
        var i = "Width" === r ? ["Left", "Right"] : ["Top", "Bottom"],
            s = r.toLowerCase(),
            o = {
                innerWidth: e.fn.innerWidth,
                innerHeight: e.fn.innerHeight,
                outerWidth: e.fn.outerWidth,
                outerHeight: e.fn.outerHeight
            };
        e.fn["inner" + r] = function (n) {
            return n === t ? o["inner" + r].call(this) : this.each(function () {
                e(this).css(s, u(this, n) + "px")
            })
        }, e.fn["outer" + r] = function (t, n) {
            return "number" != typeof t ? o["outer" + r].call(this, t) : this.each(function () {
                e(this).css(s, u(this, t, !0, n) + "px")
            })
        }
    }), e.fn.addBack || (e.fn.addBack = function (e) {
        return this.add(null == e ? this.prevObject : this.prevObject.filter(e))
    }), e("<a>").data("a-b", "a").removeData("a-b").data("a-b") && (e.fn.removeData = function (t) {
        return function (n) {
            return arguments.length ? t.call(this, e.camelCase(n)) : t.call(this)
        }
    }(e.fn.removeData)), e.ui.ie = !!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()), e.support.selectstart = "onselectstart" in document.createElement("div"), e.fn.extend({
        disableSelection: function () {
            return this.bind((e.support.selectstart ? "selectstart" : "mousedown") + ".ui-disableSelection", function (e) {
                e.preventDefault()
            })
        },
        enableSelection: function () {
            return this.unbind(".ui-disableSelection")
        }
    }), e.extend(e.ui, {
        plugin: {
            add: function (t, n, r) {
                var i, s = e.ui[t].prototype;
                for (i in r) s.plugins[i] = s.plugins[i] || [], s.plugins[i].push([n, r[i]])
            },
            call: function (e, t, n) {
                var r, i = e.plugins[t];
                if (i && e.element[0].parentNode && 11 !== e.element[0].parentNode.nodeType)
                    for (r = 0; r < i.length; r++) e.options[i[r][0]] && i[r][1].apply(e.element, n)
            }
        },
        hasScroll: function (t, n) {
            if ("hidden" === e(t).css("overflow")) return !1;
            var r = n && "left" === n ? "scrollLeft" : "scrollTop",
                i = !1;
            return t[r] > 0 ? !0 : (t[r] = 1, i = t[r] > 0, t[r] = 0, i)
        }
    }))
}(jQuery),
function (e, t) {
    var n = 0,
        r = Array.prototype.slice,
        i = e.cleanData;
    e.cleanData = function (t) {
        for (var r, n = 0; null != (r = t[n]); n++) try {
            e(r).triggerHandler("remove")
        } catch (s) {}
        i(t)
    }, e.widget = function (t, n, r) {
        var i, s, o, u, a = {},
            f = t.split(".")[0];
        t = t.split(".")[1], i = f + "-" + t, r || (r = n, n = e.Widget), e.expr[":"][i.toLowerCase()] = function (t) {
            return !!e.data(t, i)
        }, e[f] = e[f] || {}, s = e[f][t], o = e[f][t] = function (e, t) {
            return this._createWidget ? (arguments.length && this._createWidget(e, t), void 0) : new o(e, t)
        }, e.extend(o, s, {
            version: r.version,
            _proto: e.extend({}, r),
            _childConstructors: []
        }), u = new n, u.options = e.widget.extend({}, u.options), e.each(r, function (t, r) {
            return e.isFunction(r) ? (a[t] = function () {
                var e = function () {
                        return n.prototype[t].apply(this, arguments)
                    },
                    i = function (e) {
                        return n.prototype[t].apply(this, e)
                    };
                return function () {
                    var s, t = this._super,
                        n = this._superApply;
                    return this._super = e, this._superApply = i, s = r.apply(this, arguments), this._super = t, this._superApply = n, s
                }
            }(), void 0) : (a[t] = r, void 0)
        }), o.prototype = e.widget.extend(u, {
            widgetEventPrefix: s ? u.widgetEventPrefix : t
        }, a, {
            constructor: o,
            namespace: f,
            widgetName: t,
            widgetFullName: i
        }), s ? (e.each(s._childConstructors, function (t, n) {
            var r = n.prototype;
            e.widget(r.namespace + "." + r.widgetName, o, n._proto)
        }), delete s._childConstructors) : n._childConstructors.push(o), e.widget.bridge(t, o)
    }, e.widget.extend = function (n) {
        for (var u, a, i = r.call(arguments, 1), s = 0, o = i.length; o > s; s++)
            for (u in i[s]) a = i[s][u], i[s].hasOwnProperty(u) && a !== t && (n[u] = e.isPlainObject(a) ? e.isPlainObject(n[u]) ? e.widget.extend({}, n[u], a) : e.widget.extend({}, a) : a);
        return n
    }, e.widget.bridge = function (n, i) {
        var s = i.prototype.widgetFullName || n;
        e.fn[n] = function (o) {
            var u = "string" == typeof o,
                a = r.call(arguments, 1),
                f = this;
            return o = !u && a.length ? e.widget.extend.apply(null, [o].concat(a)) : o, u ? this.each(function () {
                var r, i = e.data(this, s);
                return i ? e.isFunction(i[o]) && "_" !== o.charAt(0) ? (r = i[o].apply(i, a), r !== i && r !== t ? (f = r && r.jquery ? f.pushStack(r.get()) : r, !1) : void 0) : e.error("no such method '" + o + "' for " + n + " widget instance") : e.error("cannot call methods on " + n + " prior to initialization; attempted to call method '" + o + "'")
            }) : this.each(function () {
                var t = e.data(this, s);
                t ? t.option(o || {})._init() : e.data(this, s, new i(o, this))
            }), f
        }
    }, e.Widget = function () {}, e.Widget._childConstructors = [], e.Widget.prototype = {
        widgetName: "widget",
        widgetEventPrefix: "",
        defaultElement: "<div>",
        options: {
            disabled: !1,
            create: null
        },
        _createWidget: function (t, r) {
            r = e(r || this.defaultElement || this)[0], this.element = e(r), this.uuid = n++, this.eventNamespace = "." + this.widgetName + this.uuid, this.options = e.widget.extend({}, this.options, this._getCreateOptions(), t), this.bindings = e(), this.hoverable = e(), this.focusable = e(), r !== this && (e.data(r, this.widgetFullName, this), this._on(!0, this.element, {
                remove: function (e) {
                    e.target === r && this.destroy()
                }
            }), this.document = e(r.style ? r.ownerDocument : r.document || r), this.window = e(this.document[0].defaultView || this.document[0].parentWindow)), this._create(), this._trigger("create", null, this._getCreateEventData()), this._init()
        },
        _getCreateOptions: e.noop,
        _getCreateEventData: e.noop,
        _create: e.noop,
        _init: e.noop,
        destroy: function () {
            this._destroy(), this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)), this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName + "-disabled ui-state-disabled"), this.bindings.unbind(this.eventNamespace), this.hoverable.removeClass("ui-state-hover"), this.focusable.removeClass("ui-state-focus")
        },
        _destroy: e.noop,
        widget: function () {
            return this.element
        },
        option: function (n, r) {
            var s, o, u, i = n;
            if (0 === arguments.length) return e.widget.extend({}, this.options);
            if ("string" == typeof n)
                if (i = {}, s = n.split("."), n = s.shift(), s.length) {
                    for (o = i[n] = e.widget.extend({}, this.options[n]), u = 0; u < s.length - 1; u++) o[s[u]] = o[s[u]] || {}, o = o[s[u]];
                    if (n = s.pop(), r === t) return o[n] === t ? null : o[n];
                    o[n] = r
                } else {
                    if (r === t) return this.options[n] === t ? null : this.options[n];
                    i[n] = r
                }
            return this._setOptions(i), this
        },
        _setOptions: function (e) {
            var t;
            for (t in e) this._setOption(t, e[t]);
            return this
        },
        _setOption: function (e, t) {
            return this.options[e] = t, "disabled" === e && (this.widget().toggleClass(this.widgetFullName + "-disabled ui-state-disabled", !!t).attr("aria-disabled", t), this.hoverable.removeClass("ui-state-hover"), this.focusable.removeClass("ui-state-focus")), this
        },
        enable: function () {
            return this._setOption("disabled", !1)
        },
        disable: function () {
            return this._setOption("disabled", !0)
        },
        _on: function (t, n, r) {
            var i, s = this;
            "boolean" != typeof t && (r = n, n = t, t = !1), r ? (n = i = e(n), this.bindings = this.bindings.add(n)) : (r = n, n = this.element, i = this.widget()), e.each(r, function (r, o) {
                function u() {
                    return t || s.options.disabled !== !0 && !e(this).hasClass("ui-state-disabled") ? ("string" == typeof o ? s[o] : o).apply(s, arguments) : void 0
                }
                "string" != typeof o && (u.guid = o.guid = o.guid || u.guid || e.guid++);
                var a = r.match(/^(\w+)\s*(.*)$/),
                    f = a[1] + s.eventNamespace,
                    l = a[2];
                l ? i.delegate(l, f, u) : n.bind(f, u)
            })
        },
        _off: function (e, t) {
            t = (t || "").split(" ").join(this.eventNamespace + " ") + this.eventNamespace, e.unbind(t).undelegate(t)
        },
        _delay: function (e, t) {
            function n() {
                return ("string" == typeof e ? r[e] : e).apply(r, arguments)
            }
            var r = this;
            return setTimeout(n, t || 0)
        },
        _hoverable: function (t) {
            this.hoverable = this.hoverable.add(t), this._on(t, {
                mouseenter: function (t) {
                    e(t.currentTarget).addClass("ui-state-hover")
                },
                mouseleave: function (t) {
                    e(t.currentTarget).removeClass("ui-state-hover")
                }
            })
        },
        _focusable: function (t) {
            this.focusable = this.focusable.add(t), this._on(t, {
                focusin: function (t) {
                    e(t.currentTarget).addClass("ui-state-focus")
                },
                focusout: function (t) {
                    e(t.currentTarget).removeClass("ui-state-focus")
                }
            })
        },
        _trigger: function (t, n, r) {
            var i, s, o = this.options[t];
            if (r = r || {}, n = e.Event(n), n.type = (t === this.widgetEventPrefix ? t : this.widgetEventPrefix + t).toLowerCase(), n.target = this.element[0], s = n.originalEvent, s)
                for (i in s) i in n || (n[i] = s[i]);
            return this.element.trigger(n, r), !(e.isFunction(o) && o.apply(this.element[0], [n].concat(r)) === !1 || n.isDefaultPrevented())
        }
    }, e.each({
        show: "fadeIn",
        hide: "fadeOut"
    }, function (t, n) {
        e.Widget.prototype["_" + t] = function (r, i, s) {
            "string" == typeof i && (i = {
                effect: i
            });
            var o, u = i ? i === !0 || "number" == typeof i ? n : i.effect || n : t;
            i = i || {}, "number" == typeof i && (i = {
                duration: i
            }), o = !e.isEmptyObject(i), i.complete = s, i.delay && r.delay(i.delay), o && e.effects && e.effects.effect[u] ? r[t](i) : u !== t && r[u] ? r[u](i.duration, i.easing, s) : r.queue(function (n) {
                e(this)[t](), s && s.call(r[0]), n()
            })
        }
    })
}(jQuery),
function (e) {
    var n = !1;
    e(document).mouseup(function () {
        n = !1
    }), e.widget("ui.mouse", {
        version: "1.10.1",
        options: {
            cancel: "input,textarea,button,select,option",
            distance: 1,
            delay: 0
        },
        _mouseInit: function () {
            var t = this;
            this.element.bind("mousedown." + this.widgetName, function (e) {
                return t._mouseDown(e)
            }).bind("click." + this.widgetName, function (n) {
                return !0 === e.data(n.target, t.widgetName + ".preventClickEvent") ? (e.removeData(n.target, t.widgetName + ".preventClickEvent"), n.stopImmediatePropagation(), !1) : void 0
            }), this.started = !1
        },
        _mouseDestroy: function () {
            this.element.unbind("." + this.widgetName), this._mouseMoveDelegate && e(document).unbind("mousemove." + this.widgetName, this._mouseMoveDelegate).unbind("mouseup." + this.widgetName, this._mouseUpDelegate)
        },
        _mouseDown: function (t) {
            if (!n) {
                this._mouseStarted && this._mouseUp(t), this._mouseDownEvent = t;
                var r = this,
                    i = 1 === t.which,
                    s = "string" == typeof this.options.cancel && t.target.nodeName ? e(t.target).closest(this.options.cancel).length : !1;
                return i && !s && this._mouseCapture(t) ? (this.mouseDelayMet = !this.options.delay, this.mouseDelayMet || (this._mouseDelayTimer = setTimeout(function () {
                    r.mouseDelayMet = !0
                }, this.options.delay)), this._mouseDistanceMet(t) && this._mouseDelayMet(t) && (this._mouseStarted = this._mouseStart(t) !== !1, !this._mouseStarted) ? (t.preventDefault(), !0) : (!0 === e.data(t.target, this.widgetName + ".preventClickEvent") && e.removeData(t.target, this.widgetName + ".preventClickEvent"), this._mouseMoveDelegate = function (e) {
                    return r._mouseMove(e)
                }, this._mouseUpDelegate = function (e) {
                    return r._mouseUp(e)
                }, e(document).bind("mousemove." + this.widgetName, this._mouseMoveDelegate).bind("mouseup." + this.widgetName, this._mouseUpDelegate), t.preventDefault(), n = !0, !0)) : !0
            }
        },
        _mouseMove: function (t) {
            return e.ui.ie && (!document.documentMode || document.documentMode < 9) && !t.button ? this._mouseUp(t) : this._mouseStarted ? (this._mouseDrag(t), t.preventDefault()) : (this._mouseDistanceMet(t) && this._mouseDelayMet(t) && (this._mouseStarted = this._mouseStart(this._mouseDownEvent, t) !== !1, this._mouseStarted ? this._mouseDrag(t) : this._mouseUp(t)), !this._mouseStarted)
        },
        _mouseUp: function (t) {
            return e(document).unbind("mousemove." + this.widgetName, this._mouseMoveDelegate).unbind("mouseup." + this.widgetName, this._mouseUpDelegate), this._mouseStarted && (this._mouseStarted = !1, t.target === this._mouseDownEvent.target && e.data(t.target, this.widgetName + ".preventClickEvent", !0), this._mouseStop(t)), !1
        },
        _mouseDistanceMet: function (e) {
            return Math.max(Math.abs(this._mouseDownEvent.pageX - e.pageX), Math.abs(this._mouseDownEvent.pageY - e.pageY)) >= this.options.distance
        },
        _mouseDelayMet: function () {
            return this.mouseDelayMet
        },
        _mouseStart: function () {},
        _mouseDrag: function () {},
        _mouseStop: function () {},
        _mouseCapture: function () {
            return !0
        }
    })
}(jQuery),
function (e, t) {
    function h(e, t, n) {
        return [parseFloat(e[0]) * (l.test(e[0]) ? t / 100 : 1), parseFloat(e[1]) * (l.test(e[1]) ? n / 100 : 1)]
    }

    function p(t, n) {
        return parseInt(e.css(t, n), 10) || 0
    }

    function d(t) {
        var n = t[0];
        return 9 === n.nodeType ? {
            width: t.width(),
            height: t.height(),
            offset: {
                top: 0,
                left: 0
            }
        } : e.isWindow(n) ? {
            width: t.width(),
            height: t.height(),
            offset: {
                top: t.scrollTop(),
                left: t.scrollLeft()
            }
        } : n.preventDefault ? {
            width: 0,
            height: 0,
            offset: {
                top: n.pageY,
                left: n.pageX
            }
        } : {
            width: t.outerWidth(),
            height: t.outerHeight(),
            offset: t.offset()
        }
    }
    e.ui = e.ui || {};
    var n, r = Math.max,
        i = Math.abs,
        s = Math.round,
        o = /left|center|right/,
        u = /top|center|bottom/,
        a = /[\+\-]\d+(\.[\d]+)?%?/,
        f = /^\w+/,
        l = /%$/,
        c = e.fn.position;
    e.position = {
        scrollbarWidth: function () {
            if (n !== t) return n;
            var r, i, s = e("<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),
                o = s.children()[0];
            return e("body").append(s), r = o.offsetWidth, s.css("overflow", "scroll"), i = o.offsetWidth, r === i && (i = s[0].clientWidth), s.remove(), n = r - i
        },
        getScrollInfo: function (t) {
            var n = t.isWindow ? "" : t.element.css("overflow-x"),
                r = t.isWindow ? "" : t.element.css("overflow-y"),
                i = "scroll" === n || "auto" === n && t.width < t.element[0].scrollWidth,
                s = "scroll" === r || "auto" === r && t.height < t.element[0].scrollHeight;
            return {
                width: i ? e.position.scrollbarWidth() : 0,
                height: s ? e.position.scrollbarWidth() : 0
            }
        },
        getWithinInfo: function (t) {
            var n = e(t || window),
                r = e.isWindow(n[0]);
            return {
                element: n,
                isWindow: r,
                offset: n.offset() || {
                    left: 0,
                    top: 0
                },
                scrollLeft: n.scrollLeft(),
                scrollTop: n.scrollTop(),
                width: r ? n.width() : n.outerWidth(),
                height: r ? n.height() : n.outerHeight()
            }
        }
    }, e.fn.position = function (t) {
        if (!t || !t.of) return c.apply(this, arguments);
        t = e.extend({}, t);
        var n, l, v, m, g, y, b = e(t.of),
            w = e.position.getWithinInfo(t.within),
            E = e.position.getScrollInfo(w),
            S = (t.collision || "flip").split(" "),
            x = {};
        return y = d(b), b[0].preventDefault && (t.at = "left top"), l = y.width, v = y.height, m = y.offset, g = e.extend({}, m), e.each(["my", "at"], function () {
            var n, r, e = (t[this] || "").split(" ");
            1 === e.length && (e = o.test(e[0]) ? e.concat(["center"]) : u.test(e[0]) ? ["center"].concat(e) : ["center", "center"]), e[0] = o.test(e[0]) ? e[0] : "center", e[1] = u.test(e[1]) ? e[1] : "center", n = a.exec(e[0]), r = a.exec(e[1]), x[this] = [n ? n[0] : 0, r ? r[0] : 0], t[this] = [f.exec(e[0])[0], f.exec(e[1])[0]]
        }), 1 === S.length && (S[1] = S[0]), "right" === t.at[0] ? g.left += l : "center" === t.at[0] && (g.left += l / 2), "bottom" === t.at[1] ? g.top += v : "center" === t.at[1] && (g.top += v / 2), n = h(x.at, l, v), g.left += n[0], g.top += n[1], this.each(function () {
            var o, u, a = e(this),
                f = a.outerWidth(),
                c = a.outerHeight(),
                d = p(this, "marginLeft"),
                y = p(this, "marginTop"),
                T = f + d + p(this, "marginRight") + E.width,
                N = c + y + p(this, "marginBottom") + E.height,
                C = e.extend({}, g),
                k = h(x.my, a.outerWidth(), a.outerHeight());
            "right" === t.my[0] ? C.left -= f : "center" === t.my[0] && (C.left -= f / 2), "bottom" === t.my[1] ? C.top -= c : "center" === t.my[1] && (C.top -= c / 2), C.left += k[0], C.top += k[1], e.support.offsetFractions || (C.left = s(C.left), C.top = s(C.top)), o = {
                marginLeft: d,
                marginTop: y
            }, e.each(["left", "top"], function (r, i) {
                e.ui.position[S[r]] && e.ui.position[S[r]][i](C, {
                    targetWidth: l,
                    targetHeight: v,
                    elemWidth: f,
                    elemHeight: c,
                    collisionPosition: o,
                    collisionWidth: T,
                    collisionHeight: N,
                    offset: [n[0] + k[0], n[1] + k[1]],
                    my: t.my,
                    at: t.at,
                    within: w,
                    elem: a
                })
            }), t.using && (u = function (e) {
                var n = m.left - C.left,
                    s = n + l - f,
                    o = m.top - C.top,
                    u = o + v - c,
                    h = {
                        target: {
                            element: b,
                            left: m.left,
                            top: m.top,
                            width: l,
                            height: v
                        },
                        element: {
                            element: a,
                            left: C.left,
                            top: C.top,
                            width: f,
                            height: c
                        },
                        horizontal: 0 > s ? "left" : n > 0 ? "right" : "center",
                        vertical: 0 > u ? "top" : o > 0 ? "bottom" : "middle"
                    };
                f > l && i(n + s) < l && (h.horizontal = "center"), c > v && i(o + u) < v && (h.vertical = "middle"), h.important = r(i(n), i(s)) > r(i(o), i(u)) ? "horizontal" : "vertical", t.using.call(this, e, h)
            }), a.offset(e.extend(C, {
                using: u
            }))
        })
    }, e.ui.position = {
        fit: {
            left: function (e, t) {
                var f, n = t.within,
                    i = n.isWindow ? n.scrollLeft : n.offset.left,
                    s = n.width,
                    o = e.left - t.collisionPosition.marginLeft,
                    u = i - o,
                    a = o + t.collisionWidth - s - i;
                t.collisionWidth > s ? u > 0 && 0 >= a ? (f = e.left + u + t.collisionWidth - s - i, e.left += u - f) : e.left = a > 0 && 0 >= u ? i : u > a ? i + s - t.collisionWidth : i : u > 0 ? e.left += u : a > 0 ? e.left -= a : e.left = r(e.left - o, e.left)
            },
            top: function (e, t) {
                var f, n = t.within,
                    i = n.isWindow ? n.scrollTop : n.offset.top,
                    s = t.within.height,
                    o = e.top - t.collisionPosition.marginTop,
                    u = i - o,
                    a = o + t.collisionHeight - s - i;
                t.collisionHeight > s ? u > 0 && 0 >= a ? (f = e.top + u + t.collisionHeight - s - i, e.top += u - f) : e.top = a > 0 && 0 >= u ? i : u > a ? i + s - t.collisionHeight : i : u > 0 ? e.top += u : a > 0 ? e.top -= a : e.top = r(e.top - o, e.top)
            }
        },
        flip: {
            left: function (e, t) {
                var p, d, n = t.within,
                    r = n.offset.left + n.scrollLeft,
                    s = n.width,
                    o = n.isWindow ? n.scrollLeft : n.offset.left,
                    u = e.left - t.collisionPosition.marginLeft,
                    a = u - o,
                    f = u + t.collisionWidth - s - o,
                    l = "left" === t.my[0] ? -t.elemWidth : "right" === t.my[0] ? t.elemWidth : 0,
                    c = "left" === t.at[0] ? t.targetWidth : "right" === t.at[0] ? -t.targetWidth : 0,
                    h = -2 * t.offset[0];
                0 > a ? (p = e.left + l + c + h + t.collisionWidth - s - r, (0 > p || p < i(a)) && (e.left += l + c + h)) : f > 0 && (d = e.left - t.collisionPosition.marginLeft + l + c + h - o, (d > 0 || i(d) < f) && (e.left += l + c + h))
            },
            top: function (e, t) {
                var d, v, n = t.within,
                    r = n.offset.top + n.scrollTop,
                    s = n.height,
                    o = n.isWindow ? n.scrollTop : n.offset.top,
                    u = e.top - t.collisionPosition.marginTop,
                    a = u - o,
                    f = u + t.collisionHeight - s - o,
                    l = "top" === t.my[1],
                    c = l ? -t.elemHeight : "bottom" === t.my[1] ? t.elemHeight : 0,
                    h = "top" === t.at[1] ? t.targetHeight : "bottom" === t.at[1] ? -t.targetHeight : 0,
                    p = -2 * t.offset[1];
                0 > a ? (v = e.top + c + h + p + t.collisionHeight - s - r, e.top + c + h + p > a && (0 > v || v < i(a)) && (e.top += c + h + p)) : f > 0 && (d = e.top - t.collisionPosition.marginTop + c + h + p - o, e.top + c + h + p > f && (d > 0 || i(d) < f) && (e.top += c + h + p))
            }
        },
        flipfit: {
            left: function () {
                e.ui.position.flip.left.apply(this, arguments), e.ui.position.fit.left.apply(this, arguments)
            },
            top: function () {
                e.ui.position.flip.top.apply(this, arguments), e.ui.position.fit.top.apply(this, arguments)
            }
        }
    },
    function () {
        var t, n, r, i, s, o = document.getElementsByTagName("body")[0],
            u = document.createElement("div");
        t = document.createElement(o ? "div" : "body"), r = {
            visibility: "hidden",
            width: 0,
            height: 0,
            border: 0,
            margin: 0,
            background: "none"
        }, o && e.extend(r, {
            position: "absolute",
            left: "-1000px",
            top: "-1000px"
        });
        for (s in r) t.style[s] = r[s];
        t.appendChild(u), n = o || document.documentElement, n.insertBefore(t, n.firstChild), u.style.cssText = "position: absolute; left: 10.7432222px;", i = e(u).offset().left, e.support.offsetFractions = i > 10 && 11 > i, t.innerHTML = "", n.removeChild(t)
    }()
}(jQuery),
function (e) {
    var n = 0,
        r = {},
        i = {};
    r.height = r.paddingTop = r.paddingBottom = r.borderTopWidth = r.borderBottomWidth = "hide", i.height = i.paddingTop = i.paddingBottom = i.borderTopWidth = i.borderBottomWidth = "show", e.widget("ui.accordion", {
        version: "1.10.1",
        options: {
            active: 0,
            animate: {},
            collapsible: !1,
            event: "click",
            header: "> li > :first-child,> :not(li):even",
            heightStyle: "auto",
            icons: {
                activeHeader: "ui-icon-triangle-1-s",
                header: "ui-icon-triangle-1-e"
            },
            activate: null,
            beforeActivate: null
        },
        _create: function () {
            var t = this.options;
            this.prevShow = this.prevHide = e(), this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role", "tablist"), !t.collapsible && (t.active === !1 || null == t.active) && (t.active = 0), this._processPanels(), t.active < 0 && (t.active += this.headers.length), this._refresh()
        },
        _getCreateEventData: function () {
            return {
                header: this.active,
                panel: this.active.length ? this.active.next() : e(),
                content: this.active.length ? this.active.next() : e()
            }
        },
        _createIcons: function () {
            var t = this.options.icons;
            t && (e("<span>").addClass("ui-accordion-header-icon ui-icon " + t.header).prependTo(this.headers), this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader), this.headers.addClass("ui-accordion-icons"))
        },
        _destroyIcons: function () {
            this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()
        },
        _destroy: function () {
            var e;
            this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"), this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function () {
                /^ui-accordion/.test(this.id) && this.removeAttribute("id")
            }), this._destroyIcons(), e = this.headers.next().css("display", "").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function () {
                /^ui-accordion/.test(this.id) && this.removeAttribute("id")
            }), "content" !== this.options.heightStyle && e.css("height", "")
        },
        _setOption: function (e, t) {
            return "active" === e ? (this._activate(t), void 0) : ("event" === e && (this.options.event && this._off(this.headers, this.options.event), this._setupEvents(t)), this._super(e, t), "collapsible" === e && !t && this.options.active === !1 && this._activate(0), "icons" === e && (this._destroyIcons(), t && this._createIcons()), "disabled" === e && this.headers.add(this.headers.next()).toggleClass("ui-state-disabled", !!t), void 0)
        },
        _keydown: function (t) {
            if (!t.altKey && !t.ctrlKey) {
                var n = e.ui.keyCode,
                    r = this.headers.length,
                    i = this.headers.index(t.target),
                    s = !1;
                switch (t.keyCode) {
                case n.RIGHT:
                case n.DOWN:
                    s = this.headers[(i + 1) % r];
                    break;
                case n.LEFT:
                case n.UP:
                    s = this.headers[(i - 1 + r) % r];
                    break;
                case n.SPACE:
                case n.ENTER:
                    this._eventHandler(t);
                    break;
                case n.HOME:
                    s = this.headers[0];
                    break;
                case n.END:
                    s = this.headers[r - 1]
                }
                s && (e(t.target).attr("tabIndex", -1), e(s).attr("tabIndex", 0), s.focus(), t.preventDefault())
            }
        },
        _panelKeyDown: function (t) {
            t.keyCode === e.ui.keyCode.UP && t.ctrlKey && e(t.currentTarget).prev().focus()
        },
        refresh: function () {
            var t = this.options;
            this._processPanels(), (t.active === !1 && t.collapsible === !0 || !this.headers.length) && (t.active = !1, this.active = e()), t.active === !1 ? this._activate(0) : this.active.length && !e.contains(this.element[0], this.active[0]) ? this.headers.length === this.headers.find(".ui-state-disabled").length ? (t.active = !1, this.active = e()) : this._activate(Math.max(0, t.active - 1)) : t.active = this.headers.index(this.active), this._destroyIcons(), this._refresh()
        },
        _processPanels: function () {
            this.headers = this.element.find(this.options.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"), this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide()
        },
        _refresh: function () {
            var t, r = this.options,
                i = r.heightStyle,
                s = this.element.parent(),
                o = this.accordionId = "ui-accordion-" + (this.element.attr("id") || ++n);
            this.active = this._findActive(r.active).addClass("ui-accordion-header-active ui-state-active ui-corner-top").removeClass("ui-corner-all"), this.active.next().addClass("ui-accordion-content-active").show(), this.headers.attr("role", "tab").each(function (t) {
                var n = e(this),
                    r = n.attr("id"),
                    i = n.next(),
                    s = i.attr("id");
                r || (r = o + "-header-" + t, n.attr("id", r)), s || (s = o + "-panel-" + t, i.attr("id", s)), n.attr("aria-controls", s), i.attr("aria-labelledby", r)
            }).next().attr("role", "tabpanel"), this.headers.not(this.active).attr({
                "aria-selected": "false",
                tabIndex: -1
            }).next().attr({
                "aria-expanded": "false",
                "aria-hidden": "true"
            }).hide(), this.active.length ? this.active.attr({
                "aria-selected": "true",
                tabIndex: 0
            }).next().attr({
                "aria-expanded": "true",
                "aria-hidden": "false"
            }) : this.headers.eq(0).attr("tabIndex", 0), this._createIcons(), this._setupEvents(r.event), "fill" === i ? (t = s.height(), this.element.siblings(":visible").each(function () {
                var n = e(this),
                    r = n.css("position");
                "absolute" !== r && "fixed" !== r && (t -= n.outerHeight(!0))
            }), this.headers.each(function () {
                t -= e(this).outerHeight(!0)
            }), this.headers.next().each(function () {
                e(this).height(Math.max(0, t - e(this).innerHeight() + e(this).height()))
            }).css("overflow", "auto")) : "auto" === i && (t = 0, this.headers.next().each(function () {
                t = Math.max(t, e(this).css("height", "").height())
            }).height(t))
        },
        _activate: function (t) {
            var n = this._findActive(t)[0];
            n !== this.active[0] && (n = n || this.active[0], this._eventHandler({
                target: n,
                currentTarget: n,
                preventDefault: e.noop
            }))
        },
        _findActive: function (t) {
            return "number" == typeof t ? this.headers.eq(t) : e()
        },
        _setupEvents: function (t) {
            var n = {
                keydown: "_keydown"
            };
            t && e.each(t.split(" "), function (e, t) {
                n[t] = "_eventHandler"
            }), this._off(this.headers.add(this.headers.next())), this._on(this.headers, n), this._on(this.headers.next(), {
                keydown: "_panelKeyDown"
            }), this._hoverable(this.headers), this._focusable(this.headers)
        },
        _eventHandler: function (t) {
            var n = this.options,
                r = this.active,
                i = e(t.currentTarget),
                s = i[0] === r[0],
                o = s && n.collapsible,
                u = o ? e() : i.next(),
                a = r.next(),
                f = {
                    oldHeader: r,
                    oldPanel: a,
                    newHeader: o ? e() : i,
                    newPanel: u
                };
            t.preventDefault(), s && !n.collapsible || this._trigger("beforeActivate", t, f) === !1 || (n.active = o ? !1 : this.headers.index(i), this.active = s ? e() : i, this._toggle(f), r.removeClass("ui-accordion-header-active ui-state-active"), n.icons && r.children(".ui-accordion-header-icon").removeClass(n.icons.activeHeader).addClass(n.icons.header), s || (i.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"), n.icons && i.children(".ui-accordion-header-icon").removeClass(n.icons.header).addClass(n.icons.activeHeader), i.next().addClass("ui-accordion-content-active")))
        },
        _toggle: function (t) {
            var n = t.newPanel,
                r = this.prevShow.length ? this.prevShow : t.oldPanel;
            this.prevShow.add(this.prevHide).stop(!0, !0), this.prevShow = n, this.prevHide = r, this.options.animate ? this._animate(n, r, t) : (r.hide(), n.show(), this._toggleComplete(t)), r.attr({
                "aria-expanded": "false",
                "aria-hidden": "true"
            }), r.prev().attr("aria-selected", "false"), n.length && r.length ? r.prev().attr("tabIndex", -1) : n.length && this.headers.filter(function () {
                return 0 === e(this).attr("tabIndex")
            }).attr("tabIndex", -1), n.attr({
                "aria-expanded": "true",
                "aria-hidden": "false"
            }).prev().attr({
                "aria-selected": "true",
                tabIndex: 0
            })
        },
        _animate: function (e, t, n) {
            var s, o, u, a = this,
                f = 0,
                l = e.length && (!t.length || e.index() < t.index()),
                c = this.options.animate || {},
                h = l && c.down || c,
                p = function () {
                    a._toggleComplete(n)
                };
            return "number" == typeof h && (u = h), "string" == typeof h && (o = h), o = o || h.easing || c.easing, u = u || h.duration || c.duration, t.length ? e.length ? (s = e.show().outerHeight(), t.animate(r, {
                duration: u,
                easing: o,
                step: function (e, t) {
                    t.now = Math.round(e)
                }
            }), e.hide().animate(i, {
                duration: u,
                easing: o,
                complete: p,
                step: function (e, n) {
                    n.now = Math.round(e), "height" !== n.prop ? f += n.now : "content" !== a.options.heightStyle && (n.now = Math.round(s - t.outerHeight() - f), f = 0)
                }
            }), void 0) : t.animate(r, u, o, p) : e.animate(i, u, o, p)
        },
        _toggleComplete: function (e) {
            var t = e.oldPanel;
            t.removeClass("ui-accordion-content-active").prev().removeClass("ui-corner-top").addClass("ui-corner-all"), t.length && (t.parent()[0].className = t.parent()[0].className), this._trigger("activate", null, e)
        }
    })
}(jQuery),
function (e) {
    var n = 0;
    e.widget("ui.autocomplete", {
        version: "1.10.1",
        defaultElement: "<input>",
        options: {
            appendTo: null,
            autoFocus: !1,
            delay: 300,
            minLength: 1,
            position: {
                my: "left top",
                at: "left bottom",
                collision: "none"
            },
            source: null,
            change: null,
            close: null,
            focus: null,
            open: null,
            response: null,
            search: null,
            select: null
        },
        pending: 0,
        _create: function () {
            var t, n, r, i = this.element[0].nodeName.toLowerCase(),
                s = "textarea" === i,
                o = "input" === i;
            this.isMultiLine = s ? !0 : o ? !1 : this.element.prop("isContentEditable"), this.valueMethod = this.element[s || o ? "val" : "text"], this.isNewMenu = !0, this.element.addClass("ui-autocomplete-input").attr("autocomplete", "off"), this._on(this.element, {
                keydown: function (i) {
                    if (this.element.prop("readOnly")) return t = !0, r = !0, n = !0, void 0;
                    t = !1, r = !1, n = !1;
                    var s = e.ui.keyCode;
                    switch (i.keyCode) {
                    case s.PAGE_UP:
                        t = !0, this._move("previousPage", i);
                        break;
                    case s.PAGE_DOWN:
                        t = !0, this._move("nextPage", i);
                        break;
                    case s.UP:
                        t = !0, this._keyEvent("previous", i);
                        break;
                    case s.DOWN:
                        t = !0, this._keyEvent("next", i);
                        break;
                    case s.ENTER:
                    case s.NUMPAD_ENTER:
                        this.menu.active && (t = !0, i.preventDefault(), this.menu.select(i));
                        break;
                    case s.TAB:
                        this.menu.active && this.menu.select(i);
                        break;
                    case s.ESCAPE:
                        this.menu.element.is(":visible") && (this._value(this.term), this.close(i), i.preventDefault());
                        break;
                    default:
                        n = !0, this._searchTimeout(i)
                    }
                },
                keypress: function (r) {
                    if (t) return t = !1, r.preventDefault(), void 0;
                    if (!n) {
                        var i = e.ui.keyCode;
                        switch (r.keyCode) {
                        case i.PAGE_UP:
                            this._move("previousPage", r);
                            break;
                        case i.PAGE_DOWN:
                            this._move("nextPage", r);
                            break;
                        case i.UP:
                            this._keyEvent("previous", r);
                            break;
                        case i.DOWN:
                            this._keyEvent("next", r)
                        }
                    }
                },
                input: function (e) {
                    return r ? (r = !1, e.preventDefault(), void 0) : (this._searchTimeout(e), void 0)
                },
                focus: function () {
                    this.selectedItem = null, this.previous = this._value()
                },
                blur: function (e) {
                    return this.cancelBlur ? (delete this.cancelBlur, void 0) : (clearTimeout(this.searching), this.close(e), this._change(e), void 0)
                }
            }), this._initSource(), this.menu = e("<ul>").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({
                input: e(),
                role: null
            }).hide().data("ui-menu"), this._on(this.menu.element, {
                mousedown: function (t) {
                    t.preventDefault(), this.cancelBlur = !0, this._delay(function () {
                        delete this.cancelBlur
                    });
                    var n = this.menu.element[0];
                    e(t.target).closest(".ui-menu-item").length || this._delay(function () {
                        var t = this;
                        this.document.one("mousedown", function (r) {
                            r.target !== t.element[0] && r.target !== n && !e.contains(n, r.target) && t.close()
                        })
                    })
                },
                menufocus: function (t, n) {
                    if (this.isNewMenu && (this.isNewMenu = !1, t.originalEvent && /^mouse/.test(t.originalEvent.type))) return this.menu.blur(), this.document.one("mousemove", function () {
                        e(t.target).trigger(t.originalEvent)
                    }), void 0;
                    var r = n.item.data("ui-autocomplete-item");
                    !1 !== this._trigger("focus", t, {
                        item: r
                    }) ? t.originalEvent && /^key/.test(t.originalEvent.type) && this._value(r.value) : this.liveRegion.text(r.value)
                },
                menuselect: function (e, t) {
                    var n = t.item.data("ui-autocomplete-item"),
                        r = this.previous;
                    this.element[0] !== this.document[0].activeElement && (this.element.focus(), this.previous = r, this._delay(function () {
                        this.previous = r, this.selectedItem = n
                    })), !1 !== this._trigger("select", e, {
                        item: n
                    }) && this._value(n.value), this.term = this._value(), this.close(e), this.selectedItem = n
                }
            }), this.liveRegion = e("<span>", {
                role: "status",
                "aria-live": "polite"
            }).addClass("ui-helper-hidden-accessible").insertAfter(this.element), this._on(this.window, {
                beforeunload: function () {
                    this.element.removeAttr("autocomplete")
                }
            })
        },
        _destroy: function () {
            clearTimeout(this.searching), this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"), this.menu.element.remove(), this.liveRegion.remove()
        },
        _setOption: function (e, t) {
            this._super(e, t), "source" === e && this._initSource(), "appendTo" === e && this.menu.element.appendTo(this._appendTo()), "disabled" === e && t && this.xhr && this.xhr.abort()
        },
        _appendTo: function () {
            var t = this.options.appendTo;
            return t && (t = t.jquery || t.nodeType ? e(t) : this.document.find(t).eq(0)), t || (t = this.element.closest(".ui-front")), t.length || (t = this.document[0].body), t
        },
        _initSource: function () {
            var t, n, r = this;
            e.isArray(this.options.source) ? (t = this.options.source, this.source = function (n, r) {
                r(e.ui.autocomplete.filter(t, n.term))
            }) : "string" == typeof this.options.source ? (n = this.options.source, this.source = function (t, i) {
                r.xhr && r.xhr.abort(), r.xhr = e.ajax({
                    url: n,
                    data: t,
                    dataType: "json",
                    success: function (e) {
                        i(e)
                    },
                    error: function () {
                        i([])
                    }
                })
            }) : this.source = this.options.source
        },
        _searchTimeout: function (e) {
            clearTimeout(this.searching), this.searching = this._delay(function () {
                this.term !== this._value() && (this.selectedItem = null, this.search(null, e))
            }, this.options.delay)
        },
        search: function (e, t) {
            return e = null != e ? e : this._value(), this.term = this._value(), e.length < this.options.minLength ? this.close(t) : this._trigger("search", t) !== !1 ? this._search(e) : void 0
        },
        _search: function (e) {
            this.pending++, this.element.addClass("ui-autocomplete-loading"), this.cancelSearch = !1, this.source({
                term: e
            }, this._response())
        },
        _response: function () {
            var e = this,
                t = ++n;
            return function (r) {
                t === n && e.__response(r), e.pending--, e.pending || e.element.removeClass("ui-autocomplete-loading")
            }
        },
        __response: function (e) {
            e && (e = this._normalize(e)), this._trigger("response", null, {
                content: e
            }), !this.options.disabled && e && e.length && !this.cancelSearch ? (this._suggest(e), this._trigger("open")) : this._close()
        },
        close: function (e) {
            this.cancelSearch = !0, this._close(e)
        },
        _close: function (e) {
            this.menu.element.is(":visible") && (this.menu.element.hide(), this.menu.blur(), this.isNewMenu = !0, this._trigger("close", e))
        },
        _change: function (e) {
            this.previous !== this._value() && this._trigger("change", e, {
                item: this.selectedItem
            })
        },
        _normalize: function (t) {
            return t.length && t[0].label && t[0].value ? t : e.map(t, function (t) {
                return "string" == typeof t ? {
                    label: t,
                    value: t
                } : e.extend({
                    label: t.label || t.value,
                    value: t.value || t.label
                }, t)
            })
        },
        _suggest: function (t) {
            var n = this.menu.element.empty();
            this._renderMenu(n, t), this.menu.refresh(), n.show(), this._resizeMenu(), n.position(e.extend({
                of: this.element
            }, this.options.position)), this.options.autoFocus && this.menu.next()
        },
        _resizeMenu: function () {
            var e = this.menu.element;
            e.outerWidth(Math.max(e.width("").outerWidth() + 1, this.element.outerWidth()))
        },
        _renderMenu: function (t, n) {
            var r = this;
            e.each(n, function (e, n) {
                r._renderItemData(t, n)
            })
        },
        _renderItemData: function (e, t) {
            return this._renderItem(e, t).data("ui-autocomplete-item", t)
        },
        _renderItem: function (t, n) {
            return e("<li>").append(e("<a>").text(n.label)).appendTo(t)
        },
        _move: function (e, t) {
            return this.menu.element.is(":visible") ? this.menu.isFirstItem() && /^previous/.test(e) || this.menu.isLastItem() && /^next/.test(e) ? (this._value(this.term), this.menu.blur(), void 0) : (this.menu[e](t), void 0) : (this.search(null, t), void 0)
        },
        widget: function () {
            return this.menu.element
        },
        _value: function () {
            return this.valueMethod.apply(this.element, arguments)
        },
        _keyEvent: function (e, t) {
            (!this.isMultiLine || this.menu.element.is(":visible")) && (this._move(e, t), t.preventDefault())
        }
    }), e.extend(e.ui.autocomplete, {
        escapeRegex: function (e) {
            return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&")
        },
        filter: function (t, n) {
            var r = new RegExp(e.ui.autocomplete.escapeRegex(n), "i");
            return e.grep(t, function (e) {
                return r.test(e.label || e.value || e)
            })
        }
    }), e.widget("ui.autocomplete", e.ui.autocomplete, {
        options: {
            messages: {
                noResults: "No search results.",
                results: function (e) {
                    return e + (e > 1 ? " results are" : " result is") + " available, use up and down arrow keys to navigate."
                }
            }
        },
        __response: function (e) {
            var t;
            this._superApply(arguments), this.options.disabled || this.cancelSearch || (t = e && e.length ? this.options.messages.results(e.length) : this.options.messages.noResults, this.liveRegion.text(t))
        }
    })
}(jQuery),
function (e) {
    var n, r, i, s, o = "ui-button ui-widget ui-state-default ui-corner-all",
        u = "ui-state-hover ui-state-active ",
        a = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
        f = function () {
            var t = e(this).find(":ui-button");
            setTimeout(function () {
                t.button("refresh")
            }, 1)
        },
        l = function (t) {
            var n = t.name,
                r = t.form,
                i = e([]);
            return n && (n = n.replace(/'/g, "\\'"), i = r ? e(r).find("[name='" + n + "']") : e("[name='" + n + "']", t.ownerDocument).filter(function () {
                return !this.form
            })), i
        };
    e.widget("ui.button", {
        version: "1.10.1",
        defaultElement: "<button>",
        options: {
            disabled: null,
            text: !0,
            label: null,
            icons: {
                primary: null,
                secondary: null
            }
        },
        _create: function () {
            this.element.closest("form").unbind("reset" + this.eventNamespace).bind("reset" + this.eventNamespace, f), "boolean" != typeof this.options.disabled ? this.options.disabled = !!this.element.prop("disabled") : this.element.prop("disabled", this.options.disabled), this._determineButtonType(), this.hasTitle = !!this.buttonElement.attr("title");
            var t = this,
                u = this.options,
                a = "checkbox" === this.type || "radio" === this.type,
                c = a ? "" : "ui-state-active",
                h = "ui-state-focus";
            null === u.label && (u.label = "input" === this.type ? this.buttonElement.val() : this.buttonElement.html()), this._hoverable(this.buttonElement), this.buttonElement.addClass(o).attr("role", "button").bind("mouseenter" + this.eventNamespace, function () {
                u.disabled || this === n && e(this).addClass("ui-state-active")
            }).bind("mouseleave" + this.eventNamespace, function () {
                u.disabled || e(this).removeClass(c)
            }).bind("click" + this.eventNamespace, function (e) {
                u.disabled && (e.preventDefault(), e.stopImmediatePropagation())
            }), this.element.bind("focus" + this.eventNamespace, function () {
                t.buttonElement.addClass(h)
            }).bind("blur" + this.eventNamespace, function () {
                t.buttonElement.removeClass(h)
            }), a && (this.element.bind("change" + this.eventNamespace, function () {
                s || t.refresh()
            }), this.buttonElement.bind("mousedown" + this.eventNamespace, function (e) {
                u.disabled || (s = !1, r = e.pageX, i = e.pageY)
            }).bind("mouseup" + this.eventNamespace, function (e) {
                u.disabled || (r !== e.pageX || i !== e.pageY) && (s = !0)
            })), "checkbox" === this.type ? this.buttonElement.bind("click" + this.eventNamespace, function () {
                return u.disabled || s ? !1 : void 0
            }) : "radio" === this.type ? this.buttonElement.bind("click" + this.eventNamespace, function () {
                if (u.disabled || s) return !1;
                e(this).addClass("ui-state-active"), t.buttonElement.attr("aria-pressed", "true");
                var n = t.element[0];
                l(n).not(n).map(function () {
                    return e(this).button("widget")[0]
                }).removeClass("ui-state-active").attr("aria-pressed", "false")
            }) : (this.buttonElement.bind("mousedown" + this.eventNamespace, function () {
                return u.disabled ? !1 : (e(this).addClass("ui-state-active"), n = this, t.document.one("mouseup", function () {
                    n = null
                }), void 0)
            }).bind("mouseup" + this.eventNamespace, function () {
                return u.disabled ? !1 : (e(this).removeClass("ui-state-active"), void 0)
            }).bind("keydown" + this.eventNamespace, function (t) {
                return u.disabled ? !1 : ((t.keyCode === e.ui.keyCode.SPACE || t.keyCode === e.ui.keyCode.ENTER) && e(this).addClass("ui-state-active"), void 0)
            }).bind("keyup" + this.eventNamespace + " blur" + this.eventNamespace, function () {
                e(this).removeClass("ui-state-active")
            }), this.buttonElement.is("a") && this.buttonElement.keyup(function (t) {
                t.keyCode === e.ui.keyCode.SPACE && e(this).click()
            })), this._setOption("disabled", u.disabled), this._resetButton()
        },
        _determineButtonType: function () {
            var e, t, n;
            this.type = this.element.is("[type=checkbox]") ? "checkbox" : this.element.is("[type=radio]") ? "radio" : this.element.is("input") ? "input" : "button", "checkbox" === this.type || "radio" === this.type ? (e = this.element.parents().last(), t = "label[for='" + this.element.attr("id") + "']", this.buttonElement = e.find(t), this.buttonElement.length || (e = e.length ? e.siblings() : this.element.siblings(), this.buttonElement = e.filter(t), this.buttonElement.length || (this.buttonElement = e.find(t))), this.element.addClass("ui-helper-hidden-accessible"), n = this.element.is(":checked"), n && this.buttonElement.addClass("ui-state-active"), this.buttonElement.prop("aria-pressed", n)) : this.buttonElement = this.element
        },
        widget: function () {
            return this.buttonElement
        },
        _destroy: function () {
            this.element.removeClass("ui-helper-hidden-accessible"), this.buttonElement.removeClass(o + " " + u + " " + a).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()), this.hasTitle || this.buttonElement.removeAttr("title")
        },
        _setOption: function (e, t) {
            return this._super(e, t), "disabled" === e ? (t ? this.element.prop("disabled", !0) : this.element.prop("disabled", !1), void 0) : (this._resetButton(), void 0)
        },
        refresh: function () {
            var t = this.element.is("input, button") ? this.element.is(":disabled") : this.element.hasClass("ui-button-disabled");
            t !== this.options.disabled && this._setOption("disabled", t), "radio" === this.type ? l(this.element[0]).each(function () {
                e(this).is(":checked") ? e(this).button("widget").addClass("ui-state-active").attr("aria-pressed", "true") : e(this).button("widget").removeClass("ui-state-active").attr("aria-pressed", "false")
            }) : "checkbox" === this.type && (this.element.is(":checked") ? this.buttonElement.addClass("ui-state-active").attr("aria-pressed", "true") : this.buttonElement.removeClass("ui-state-active").attr("aria-pressed", "false"))
        },
        _resetButton: function () {
            if ("input" === this.type) return this.options.label && this.element.val(this.options.label), void 0;
            var t = this.buttonElement.removeClass(a),
                n = e("<span></span>", this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(t.empty()).text(),
                r = this.options.icons,
                i = r.primary && r.secondary,
                s = [];
            r.primary || r.secondary ? (this.options.text && s.push("ui-button-text-icon" + (i ? "s" : r.primary ? "-primary" : "-secondary")), r.primary && t.prepend("<span class='ui-button-icon-primary ui-icon " + r.primary + "'></span>"), r.secondary && t.append("<span class='ui-button-icon-secondary ui-icon " + r.secondary + "'></span>"), this.options.text || (s.push(i ? "ui-button-icons-only" : "ui-button-icon-only"), this.hasTitle || t.attr("title", e.trim(n)))) : s.push("ui-button-text-only"), t.addClass(s.join(" "))
        }
    }), e.widget("ui.buttonset", {
        version: "1.10.1",
        options: {
            items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
        },
        _create: function () {
            this.element.addClass("ui-buttonset")
        },
        _init: function () {
            this.refresh()
        },
        _setOption: function (e, t) {
            "disabled" === e && this.buttons.button("option", e, t), this._super(e, t)
        },
        refresh: function () {
            var t = "rtl" === this.element.css("direction");
            this.buttons = this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function () {
                return e(this).button("widget")[0]
            }).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(t ? "ui-corner-right" : "ui-corner-left").end().filter(":last").addClass(t ? "ui-corner-left" : "ui-corner-right").end().end()
        },
        _destroy: function () {
            this.element.removeClass("ui-buttonset"), this.buttons.map(function () {
                return e(this).button("widget")[0]
            }).removeClass("ui-corner-left ui-corner-right").end().button("destroy")
        }
    })
}(jQuery),
function (e, t) {
    function s() {
        this._curInst = null, this._keyEvent = !1, this._disabledInputs = [], this._datepickerShowing = !1, this._inDialog = !1, this._mainDivId = "ui-datepicker-div", this._inlineClass = "ui-datepicker-inline", this._appendClass = "ui-datepicker-append", this._triggerClass = "ui-datepicker-trigger", this._dialogClass = "ui-datepicker-dialog", this._disableClass = "ui-datepicker-disabled", this._unselectableClass = "ui-datepicker-unselectable", this._currentClass = "ui-datepicker-current-day", this._dayOverClass = "ui-datepicker-days-cell-over", this.regional = [], this.regional[""] = {
            closeText: "Done",
            prevText: "Prev",
            nextText: "Next",
            currentText: "Today",
            monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
            monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
            dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
            dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
            dayNamesMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
            weekHeader: "Wk",
            dateFormat: "mm/dd/yy",
            firstDay: 0,
            isRTL: !1,
            showMonthAfterYear: !1,
            yearSuffix: ""
        }, this._defaults = {
            showOn: "focus",
            showAnim: "fadeIn",
            showOptions: {},
            defaultDate: null,
            appendText: "",
            buttonText: "...",
            buttonImage: "",
            buttonImageOnly: !1,
            hideIfNoPrevNext: !1,
            navigationAsDateFormat: !1,
            gotoCurrent: !1,
            changeMonth: !1,
            changeYear: !1,
            yearRange: "c-10:c+10",
            showOtherMonths: !1,
            selectOtherMonths: !1,
            showWeek: !1,
            calculateWeek: this.iso8601Week,
            shortYearCutoff: "+10",
            minDate: null,
            maxDate: null,
            duration: "fast",
            beforeShowDay: null,
            beforeShow: null,
            onSelect: null,
            onChangeMonthYear: null,
            onClose: null,
            numberOfMonths: 1,
            showCurrentAtPos: 0,
            stepMonths: 1,
            stepBigMonths: 12,
            altField: "",
            altFormat: "",
            constrainInput: !0,
            showButtonPanel: !1,
            autoSize: !1,
            disabled: !1
        }, e.extend(this._defaults, this.regional[""]), this.dpDiv = o(e("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))
    }

    function o(t) {
        var n = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
        return t.delegate(n, "mouseout", function () {
            e(this).removeClass("ui-state-hover"), -1 !== this.className.indexOf("ui-datepicker-prev") && e(this).removeClass("ui-datepicker-prev-hover"), -1 !== this.className.indexOf("ui-datepicker-next") && e(this).removeClass("ui-datepicker-next-hover")
        }).delegate(n, "mouseover", function () {
            e.datepicker._isDisabledDatepicker(i.inline ? t.parent()[0] : i.input[0]) || (e(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"), e(this).addClass("ui-state-hover"), -1 !== this.className.indexOf("ui-datepicker-prev") && e(this).addClass("ui-datepicker-prev-hover"), -1 !== this.className.indexOf("ui-datepicker-next") && e(this).addClass("ui-datepicker-next-hover"))
        })
    }

    function u(t, n) {
        e.extend(t, n);
        for (var r in n) null == n[r] && (t[r] = n[r]);
        return t
    }
    e.extend(e.ui, {
        datepicker: {
            version: "1.10.1"
        }
    });
    var i, n = "datepicker",
        r = (new Date).getTime();
    e.extend(s.prototype, {
        markerClassName: "hasDatepicker",
        maxRows: 4,
        _widgetDatepicker: function () {
            return this.dpDiv
        },
        setDefaults: function (e) {
            return u(this._defaults, e || {}), this
        },
        _attachDatepicker: function (t, n) {
            var r, i, s;
            r = t.nodeName.toLowerCase(), i = "div" === r || "span" === r, t.id || (this.uuid += 1, t.id = "dp" + this.uuid), s = this._newInst(e(t), i), s.settings = e.extend({}, n || {}), "input" === r ? this._connectDatepicker(t, s) : i && this._inlineDatepicker(t, s)
        },
        _newInst: function (t, n) {
            var r = t[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1");
            return {
                id: r,
                input: t,
                selectedDay: 0,
                selectedMonth: 0,
                selectedYear: 0,
                drawMonth: 0,
                drawYear: 0,
                inline: n,
                dpDiv: n ? o(e("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")) : this.dpDiv
            }
        },
        _connectDatepicker: function (t, r) {
            var i = e(t);
            r.append = e([]), r.trigger = e([]), i.hasClass(this.markerClassName) || (this._attachments(i, r), i.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp), this._autoSize(r), e.data(t, n, r), r.settings.disabled && this._disableDatepicker(t))
        },
        _attachments: function (t, n) {
            var r, i, s, o = this._get(n, "appendText"),
                u = this._get(n, "isRTL");
            n.append && n.append.remove(), o && (n.append = e("<span class='" + this._appendClass + "'>" + o + "</span>"), t[u ? "before" : "after"](n.append)), t.unbind("focus", this._showDatepicker), n.trigger && n.trigger.remove(), r = this._get(n, "showOn"), ("focus" === r || "both" === r) && t.focus(this._showDatepicker), ("button" === r || "both" === r) && (i = this._get(n, "buttonText"), s = this._get(n, "buttonImage"), n.trigger = e(this._get(n, "buttonImageOnly") ? e("<img/>").addClass(this._triggerClass).attr({
                src: s,
                alt: i,
                title: i
            }) : e("<button type='button'></button>").addClass(this._triggerClass).html(s ? e("<img/>").attr({
                src: s,
                alt: i,
                title: i
            }) : i)), t[u ? "before" : "after"](n.trigger), n.trigger.click(function () {
                return e.datepicker._datepickerShowing && e.datepicker._lastInput === t[0] ? e.datepicker._hideDatepicker() : e.datepicker._datepickerShowing && e.datepicker._lastInput !== t[0] ? (e.datepicker._hideDatepicker(), e.datepicker._showDatepicker(t[0])) : e.datepicker._showDatepicker(t[0]), !1
            }))
        },
        _autoSize: function (e) {
            if (this._get(e, "autoSize") && !e.inline) {
                var t, n, r, i, s = new Date(2009, 11, 20),
                    o = this._get(e, "dateFormat");
                o.match(/[DM]/) && (t = function (e) {
                    for (n = 0, r = 0, i = 0; i < e.length; i++) e[i].length > n && (n = e[i].length, r = i);
                    return r
                }, s.setMonth(t(this._get(e, o.match(/MM/) ? "monthNames" : "monthNamesShort"))), s.setDate(t(this._get(e, o.match(/DD/) ? "dayNames" : "dayNamesShort")) + 20 - s.getDay())), e.input.attr("size", this._formatDate(e, s).length)
            }
        },
        _inlineDatepicker: function (t, r) {
            var i = e(t);
            i.hasClass(this.markerClassName) || (i.addClass(this.markerClassName).append(r.dpDiv), e.data(t, n, r), this._setDate(r, this._getDefaultDate(r), !0), this._updateDatepicker(r), this._updateAlternate(r), r.settings.disabled && this._disableDatepicker(t), r.dpDiv.css("display", "block"))
        },
        _dialogDatepicker: function (t, r, i, s, o) {
            var a, f, l, c, h, p = this._dialogInst;
            return p || (this.uuid += 1, a = "dp" + this.uuid, this._dialogInput = e("<input type='text' id='" + a + "' style='position: absolute; top: -100px; width: 0px;'/>"), this._dialogInput.keydown(this._doKeyDown), e("body").append(this._dialogInput), p = this._dialogInst = this._newInst(this._dialogInput, !1), p.settings = {}, e.data(this._dialogInput[0], n, p)), u(p.settings, s || {}), r = r && r.constructor === Date ? this._formatDate(p, r) : r, this._dialogInput.val(r), this._pos = o ? o.length ? o : [o.pageX, o.pageY] : null, this._pos || (f = document.documentElement.clientWidth, l = document.documentElement.clientHeight, c = document.documentElement.scrollLeft || document.body.scrollLeft, h = document.documentElement.scrollTop || document.body.scrollTop, this._pos = [f / 2 - 100 + c, l / 2 - 150 + h]), this._dialogInput.css("left", this._pos[0] + 20 + "px").css("top", this._pos[1] + "px"), p.settings.onSelect = i, this._inDialog = !0, this.dpDiv.addClass(this._dialogClass), this._showDatepicker(this._dialogInput[0]), e.blockUI && e.blockUI(this.dpDiv), e.data(this._dialogInput[0], n, p), this
        },
        _destroyDatepicker: function (t) {
            var r, i = e(t),
                s = e.data(t, n);
            i.hasClass(this.markerClassName) && (r = t.nodeName.toLowerCase(), e.removeData(t, n), "input" === r ? (s.append.remove(), s.trigger.remove(), i.removeClass(this.markerClassName).unbind("focus", this._showDatepicker).unbind("keydown", this._doKeyDown).unbind("keypress", this._doKeyPress).unbind("keyup", this._doKeyUp)) : ("div" === r || "span" === r) && i.removeClass(this.markerClassName).empty())
        },
        _enableDatepicker: function (t) {
            var r, i, s = e(t),
                o = e.data(t, n);
            s.hasClass(this.markerClassName) && (r = t.nodeName.toLowerCase(), "input" === r ? (t.disabled = !1, o.trigger.filter("button").each(function () {
                this.disabled = !1
            }).end().filter("img").css({
                opacity: "1.0",
                cursor: ""
            })) : ("div" === r || "span" === r) && (i = s.children("." + this._inlineClass), i.children().removeClass("ui-state-disabled"), i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled", !1)), this._disabledInputs = e.map(this._disabledInputs, function (e) {
                return e === t ? null : e
            }))
        },
        _disableDatepicker: function (t) {
            var r, i, s = e(t),
                o = e.data(t, n);
            s.hasClass(this.markerClassName) && (r = t.nodeName.toLowerCase(), "input" === r ? (t.disabled = !0, o.trigger.filter("button").each(function () {
                this.disabled = !0
            }).end().filter("img").css({
                opacity: "0.5",
                cursor: "default"
            })) : ("div" === r || "span" === r) && (i = s.children("." + this._inlineClass), i.children().addClass("ui-state-disabled"), i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled", !0)), this._disabledInputs = e.map(this._disabledInputs, function (e) {
                return e === t ? null : e
            }), this._disabledInputs[this._disabledInputs.length] = t)
        },
        _isDisabledDatepicker: function (e) {
            if (!e) return !1;
            for (var t = 0; t < this._disabledInputs.length; t++)
                if (this._disabledInputs[t] === e) return !0;
            return !1
        },
        _getInst: function (t) {
            try {
                return e.data(t, n)
            } catch (r) {
                throw "Missing instance data for this datepicker"
            }
        },
        _optionDatepicker: function (n, r, i) {
            var s, o, a, f, l = this._getInst(n);
            return 2 === arguments.length && "string" == typeof r ? "defaults" === r ? e.extend({}, e.datepicker._defaults) : l ? "all" === r ? e.extend({}, l.settings) : this._get(l, r) : null : (s = r || {}, "string" == typeof r && (s = {}, s[r] = i), l && (this._curInst === l && this._hideDatepicker(), o = this._getDateDatepicker(n, !0), a = this._getMinMaxDate(l, "min"), f = this._getMinMaxDate(l, "max"), u(l.settings, s), null !== a && s.dateFormat !== t && s.minDate === t && (l.settings.minDate = this._formatDate(l, a)), null !== f && s.dateFormat !== t && s.maxDate === t && (l.settings.maxDate = this._formatDate(l, f)), "disabled" in s && (s.disabled ? this._disableDatepicker(n) : this._enableDatepicker(n)), this._attachments(e(n), l), this._autoSize(l), this._setDate(l, o), this._updateAlternate(l), this._updateDatepicker(l)), void 0)
        },
        _changeDatepicker: function (e, t, n) {
            this._optionDatepicker(e, t, n)
        },
        _refreshDatepicker: function (e) {
            var t = this._getInst(e);
            t && this._updateDatepicker(t)
        },
        _setDateDatepicker: function (e, t) {
            var n = this._getInst(e);
            n && (this._setDate(n, t), this._updateDatepicker(n), this._updateAlternate(n))
        },
        _getDateDatepicker: function (e, t) {
            var n = this._getInst(e);
            return n && !n.inline && this._setDateFromField(n, t), n ? this._getDate(n) : null
        },
        _doKeyDown: function (t) {
            var n, r, i, s = e.datepicker._getInst(t.target),
                o = !0,
                u = s.dpDiv.is(".ui-datepicker-rtl");
            if (s._keyEvent = !0, e.datepicker._datepickerShowing) switch (t.keyCode) {
            case 9:
                e.datepicker._hideDatepicker(), o = !1;
                break;
            case 13:
                return i = e("td." + e.datepicker._dayOverClass + ":not(." + e.datepicker._currentClass + ")", s.dpDiv), i[0] && e.datepicker._selectDay(t.target, s.selectedMonth, s.selectedYear, i[0]), n = e.datepicker._get(s, "onSelect"), n ? (r = e.datepicker._formatDate(s), n.apply(s.input ? s.input[0] : null, [r, s])) : e.datepicker._hideDatepicker(), !1;
            case 27:
                e.datepicker._hideDatepicker();
                break;
            case 33:
                e.datepicker._adjustDate(t.target, t.ctrlKey ? -e.datepicker._get(s, "stepBigMonths") : -e.datepicker._get(s, "stepMonths"), "M");
                break;
            case 34:
                e.datepicker._adjustDate(t.target, t.ctrlKey ? +e.datepicker._get(s, "stepBigMonths") : +e.datepicker._get(s, "stepMonths"), "M");
                break;
            case 35:
                (t.ctrlKey || t.metaKey) && e.datepicker._clearDate(t.target), o = t.ctrlKey || t.metaKey;
                break;
            case 36:
                (t.ctrlKey || t.metaKey) && e.datepicker._gotoToday(t.target), o = t.ctrlKey || t.metaKey;
                break;
            case 37:
                (t.ctrlKey || t.metaKey) && e.datepicker._adjustDate(t.target, u ? 1 : -1, "D"), o = t.ctrlKey || t.metaKey, t.originalEvent.altKey && e.datepicker._adjustDate(t.target, t.ctrlKey ? -e.datepicker._get(s, "stepBigMonths") : -e.datepicker._get(s, "stepMonths"), "M");
                break;
            case 38:
                (t.ctrlKey || t.metaKey) && e.datepicker._adjustDate(t.target, -7, "D"), o = t.ctrlKey || t.metaKey;
                break;
            case 39:
                (t.ctrlKey || t.metaKey) && e.datepicker._adjustDate(t.target, u ? -1 : 1, "D"), o = t.ctrlKey || t.metaKey, t.originalEvent.altKey && e.datepicker._adjustDate(t.target, t.ctrlKey ? +e.datepicker._get(s, "stepBigMonths") : +e.datepicker._get(s, "stepMonths"), "M");
                break;
            case 40:
                (t.ctrlKey || t.metaKey) && e.datepicker._adjustDate(t.target, 7, "D"), o = t.ctrlKey || t.metaKey;
                break;
            default:
                o = !1
            } else 36 === t.keyCode && t.ctrlKey ? e.datepicker._showDatepicker(this) : o = !1;
            o && (t.preventDefault(), t.stopPropagation())
        },
        _doKeyPress: function (t) {
            var n, r, i = e.datepicker._getInst(t.target);
            return e.datepicker._get(i, "constrainInput") ? (n = e.datepicker._possibleChars(e.datepicker._get(i, "dateFormat")), r = String.fromCharCode(null == t.charCode ? t.keyCode : t.charCode), t.ctrlKey || t.metaKey || " " > r || !n || n.indexOf(r) > -1) : void 0
        },
        _doKeyUp: function (t) {
            var n, r = e.datepicker._getInst(t.target);
            if (r.input.val() !== r.lastVal) try {
                n = e.datepicker.parseDate(e.datepicker._get(r, "dateFormat"), r.input ? r.input.val() : null, e.datepicker._getFormatConfig(r)), n && (e.datepicker._setDateFromField(r), e.datepicker._updateAlternate(r), e.datepicker._updateDatepicker(r))
            } catch (i) {}
            return !0
        },
        _showDatepicker: function (t) {
            if (t = t.target || t, "input" !== t.nodeName.toLowerCase() && (t = e("input", t.parentNode)[0]), !e.datepicker._isDisabledDatepicker(t) && e.datepicker._lastInput !== t) {
                var n, r, i, s, o, a, f;
                n = e.datepicker._getInst(t), e.datepicker._curInst && e.datepicker._curInst !== n && (e.datepicker._curInst.dpDiv.stop(!0, !0), n && e.datepicker._datepickerShowing && e.datepicker._hideDatepicker(e.datepicker._curInst.input[0])), r = e.datepicker._get(n, "beforeShow"), i = r ? r.apply(t, [t, n]) : {}, i !== !1 && (u(n.settings, i), n.lastVal = null, e.datepicker._lastInput = t, e.datepicker._setDateFromField(n), e.datepicker._inDialog && (t.value = ""), e.datepicker._pos || (e.datepicker._pos = e.datepicker._findPos(t), e.datepicker._pos[1] += t.offsetHeight), s = !1, e(t).parents().each(function () {
                    return s |= "fixed" === e(this).css("position"), !s
                }), o = {
                    left: e.datepicker._pos[0],
                    top: e.datepicker._pos[1]
                }, e.datepicker._pos = null, n.dpDiv.empty(), n.dpDiv.css({
                    position: "absolute",
                    display: "block",
                    top: "-1000px"
                }), e.datepicker._updateDatepicker(n), o = e.datepicker._checkOffset(n, o, s), n.dpDiv.css({
                    position: e.datepicker._inDialog && e.blockUI ? "static" : s ? "fixed" : "absolute",
                    display: "none",
                    left: o.left + "px",
                    top: o.top + "px"
                }), n.inline || (a = e.datepicker._get(n, "showAnim"), f = e.datepicker._get(n, "duration"), n.dpDiv.zIndex(e(t).zIndex() + 1), e.datepicker._datepickerShowing = !0, e.effects && e.effects.effect[a] ? n.dpDiv.show(a, e.datepicker._get(n, "showOptions"), f) : n.dpDiv[a || "show"](a ? f : null), n.input.is(":visible") && !n.input.is(":disabled") && n.input.focus(), e.datepicker._curInst = n))
            }
        },
        _updateDatepicker: function (t) {
            this.maxRows = 4, i = t, t.dpDiv.empty().append(this._generateHTML(t)), this._attachHandlers(t), t.dpDiv.find("." + this._dayOverClass + " a").mouseover();
            var n, r = this._getNumberOfMonths(t),
                s = r[1],
                o = 17;
            t.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""), s > 1 && t.dpDiv.addClass("ui-datepicker-multi-" + s).css("width", o * s + "em"), t.dpDiv[(1 !== r[0] || 1 !== r[1] ? "add" : "remove") + "Class"]("ui-datepicker-multi"), t.dpDiv[(this._get(t, "isRTL") ? "add" : "remove") + "Class"]("ui-datepicker-rtl"), t === e.datepicker._curInst && e.datepicker._datepickerShowing && t.input && t.input.is(":visible") && !t.input.is(":disabled") && t.input[0] !== document.activeElement && t.input.focus(), t.yearshtml && (n = t.yearshtml, setTimeout(function () {
                n === t.yearshtml && t.yearshtml && t.dpDiv.find("select.ui-datepicker-year:first").replaceWith(t.yearshtml), n = t.yearshtml = null
            }, 0))
        },
        _getBorders: function (e) {
            var t = function (e) {
                return {
                    thin: 1,
                    medium: 2,
                    thick: 3
                }[e] || e
            };
            return [parseFloat(t(e.css("border-left-width"))), parseFloat(t(e.css("border-top-width")))]
        },
        _checkOffset: function (t, n, r) {
            var i = t.dpDiv.outerWidth(),
                s = t.dpDiv.outerHeight(),
                o = t.input ? t.input.outerWidth() : 0,
                u = t.input ? t.input.outerHeight() : 0,
                a = document.documentElement.clientWidth + (r ? 0 : e(document).scrollLeft()),
                f = document.documentElement.clientHeight + (r ? 0 : e(document).scrollTop());
            return n.left -= this._get(t, "isRTL") ? i - o : 0, n.left -= r && n.left === t.input.offset().left ? e(document).scrollLeft() : 0, n.top -= r && n.top === t.input.offset().top + u ? e(document).scrollTop() : 0, n.left -= Math.min(n.left, n.left + i > a && a > i ? Math.abs(n.left + i - a) : 0), n.top -= Math.min(n.top, n.top + s > f && f > s ? Math.abs(s + u) : 0), n
        },
        _findPos: function (t) {
            for (var n, r = this._getInst(t), i = this._get(r, "isRTL"); t && ("hidden" === t.type || 1 !== t.nodeType || e.expr.filters.hidden(t));) t = t[i ? "previousSibling" : "nextSibling"];
            return n = e(t).offset(), [n.left, n.top]
        },
        _hideDatepicker: function (t) {
            var r, i, s, o, u = this._curInst;
            !u || t && u !== e.data(t, n) || this._datepickerShowing && (r = this._get(u, "showAnim"), i = this._get(u, "duration"), s = function () {
                e.datepicker._tidyDialog(u)
            }, e.effects && (e.effects.effect[r] || e.effects[r]) ? u.dpDiv.hide(r, e.datepicker._get(u, "showOptions"), i, s) : u.dpDiv["slideDown" === r ? "slideUp" : "fadeIn" === r ? "fadeOut" : "hide"](r ? i : null, s), r || s(), this._datepickerShowing = !1, o = this._get(u, "onClose"), o && o.apply(u.input ? u.input[0] : null, [u.input ? u.input.val() : "", u]), this._lastInput = null, this._inDialog && (this._dialogInput.css({
                position: "absolute",
                left: "0",
                top: "-100px"
            }), e.blockUI && (e.unblockUI(), e("body").append(this.dpDiv))), this._inDialog = !1)
        },
        _tidyDialog: function (e) {
            e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")
        },
        _checkExternalClick: function (t) {
            if (e.datepicker._curInst) {
                var n = e(t.target),
                    r = e.datepicker._getInst(n[0]);
                (n[0].id !== e.datepicker._mainDivId && 0 === n.parents("#" + e.datepicker._mainDivId).length && !n.hasClass(e.datepicker.markerClassName) && !n.closest("." + e.datepicker._triggerClass).length && e.datepicker._datepickerShowing && (!e.datepicker._inDialog || !e.blockUI) || n.hasClass(e.datepicker.markerClassName) && e.datepicker._curInst !== r) && e.datepicker._hideDatepicker()
            }
        },
        _adjustDate: function (t, n, r) {
            var i = e(t),
                s = this._getInst(i[0]);
            this._isDisabledDatepicker(i[0]) || (this._adjustInstDate(s, n + ("M" === r ? this._get(s, "showCurrentAtPos") : 0), r), this._updateDatepicker(s))
        },
        _gotoToday: function (t) {
            var n, r = e(t),
                i = this._getInst(r[0]);
            this._get(i, "gotoCurrent") && i.currentDay ? (i.selectedDay = i.currentDay, i.drawMonth = i.selectedMonth = i.currentMonth, i.drawYear = i.selectedYear = i.currentYear) : (n = new Date, i.selectedDay = n.getDate(), i.drawMonth = i.selectedMonth = n.getMonth(), i.drawYear = i.selectedYear = n.getFullYear()), this._notifyChange(i), this._adjustDate(r)
        },
        _selectMonthYear: function (t, n, r) {
            var i = e(t),
                s = this._getInst(i[0]);
            s["selected" + ("M" === r ? "Month" : "Year")] = s["draw" + ("M" === r ? "Month" : "Year")] = parseInt(n.options[n.selectedIndex].value, 10), this._notifyChange(s), this._adjustDate(i)
        },
        _selectDay: function (t, n, r, i) {
            var s, o = e(t);
            e(i).hasClass(this._unselectableClass) || this._isDisabledDatepicker(o[0]) || (s = this._getInst(o[0]), s.selectedDay = s.currentDay = e("a", i).html(), s.selectedMonth = s.currentMonth = n, s.selectedYear = s.currentYear = r, this._selectDate(t, this._formatDate(s, s.currentDay, s.currentMonth, s.currentYear)))
        },
        _clearDate: function (t) {
            var n = e(t);
            this._selectDate(n, "")
        },
        _selectDate: function (t, n) {
            var r, i = e(t),
                s = this._getInst(i[0]);
            n = null != n ? n : this._formatDate(s), s.input && s.input.val(n), this._updateAlternate(s), r = this._get(s, "onSelect"), r ? r.apply(s.input ? s.input[0] : null, [n, s]) : s.input && s.input.trigger("change"), s.inline ? this._updateDatepicker(s) : (this._hideDatepicker(), this._lastInput = s.input[0], "object" != typeof s.input[0] && s.input.focus(), this._lastInput = null)
        },
        _updateAlternate: function (t) {
            var n, r, i, s = this._get(t, "altField");
            s && (n = this._get(t, "altFormat") || this._get(t, "dateFormat"), r = this._getDate(t), i = this.formatDate(n, r, this._getFormatConfig(t)), e(s).each(function () {
                e(this).val(i)
            }))
        },
        noWeekends: function (e) {
            var t = e.getDay();
            return [t > 0 && 6 > t, ""]
        },
        iso8601Week: function (e) {
            var t, n = new Date(e.getTime());
            return n.setDate(n.getDate() + 4 - (n.getDay() || 7)), t = n.getTime(), n.setMonth(0), n.setDate(1), Math.floor(Math.round((t - n) / 864e5) / 7) + 1
        },
        parseDate: function (t, n, r) {
            if (null == t || null == n) throw "Invalid arguments";
            if (n = "object" == typeof n ? n.toString() : n + "", "" === n) return null;
            var i, s, o, b, u = 0,
                a = (r ? r.shortYearCutoff : null) || this._defaults.shortYearCutoff,
                f = "string" != typeof a ? a : (new Date).getFullYear() % 100 + parseInt(a, 10),
                l = (r ? r.dayNamesShort : null) || this._defaults.dayNamesShort,
                c = (r ? r.dayNames : null) || this._defaults.dayNames,
                h = (r ? r.monthNamesShort : null) || this._defaults.monthNamesShort,
                p = (r ? r.monthNames : null) || this._defaults.monthNames,
                d = -1,
                v = -1,
                m = -1,
                g = -1,
                y = !1,
                w = function (e) {
                    var n = i + 1 < t.length && t.charAt(i + 1) === e;
                    return n && i++, n
                },
                E = function (e) {
                    var t = w(e),
                        r = "@" === e ? 14 : "!" === e ? 20 : "y" === e && t ? 4 : "o" === e ? 3 : 2,
                        i = new RegExp("^\\d{1," + r + "}"),
                        s = n.substring(u).match(i);
                    if (!s) throw "Missing number at position " + u;
                    return u += s[0].length, parseInt(s[0], 10)
                },
                S = function (t, r, i) {
                    var s = -1,
                        o = e.map(w(t) ? i : r, function (e, t) {
                            return [
                                [t, e]
                            ]
                        }).sort(function (e, t) {
                            return -(e[1].length - t[1].length)
                        });
                    if (e.each(o, function (e, t) {
                        var r = t[1];
                        return n.substr(u, r.length).toLowerCase() === r.toLowerCase() ? (s = t[0], u += r.length, !1) : void 0
                    }), -1 !== s) return s + 1;
                    throw "Unknown name at position " + u
                },
                x = function () {
                    if (n.charAt(u) !== t.charAt(i)) throw "Unexpected literal at position " + u;
                    u++
                };
            for (i = 0; i < t.length; i++)
                if (y) "'" !== t.charAt(i) || w("'") ? x() : y = !1;
                else switch (t.charAt(i)) {
                case "d":
                    m = E("d");
                    break;
                case "D":
                    S("D", l, c);
                    break;
                case "o":
                    g = E("o");
                    break;
                case "m":
                    v = E("m");
                    break;
                case "M":
                    v = S("M", h, p);
                    break;
                case "y":
                    d = E("y");
                    break;
                case "@":
                    b = new Date(E("@")), d = b.getFullYear(), v = b.getMonth() + 1, m = b.getDate();
                    break;
                case "!":
                    b = new Date((E("!") - this._ticksTo1970) / 1e4), d = b.getFullYear(), v = b.getMonth() + 1, m = b.getDate();
                    break;
                case "'":
                    w("'") ? x() : y = !0;
                    break;
                default:
                    x()
                }
                if (u < n.length && (o = n.substr(u), !/^\s+/.test(o))) throw "Extra/unparsed characters found in date: " + o;
            if (-1 === d ? d = (new Date).getFullYear() : 100 > d && (d += (new Date).getFullYear() - (new Date).getFullYear() % 100 + (f >= d ? 0 : -100)), g > -1)
                for (v = 1, m = g;;) {
                    if (s = this._getDaysInMonth(d, v - 1), s >= m) break;
                    v++, m -= s
                }
            if (b = this._daylightSavingAdjust(new Date(d, v - 1, m)), b.getFullYear() !== d || b.getMonth() + 1 !== v || b.getDate() !== m) throw "Invalid date";
            return b
        },
        ATOM: "yy-mm-dd",
        COOKIE: "D, dd M yy",
        ISO_8601: "yy-mm-dd",
        RFC_822: "D, d M y",
        RFC_850: "DD, dd-M-y",
        RFC_1036: "D, d M y",
        RFC_1123: "D, d M yy",
        RFC_2822: "D, d M yy",
        RSS: "D, d M y",
        TICKS: "!",
        TIMESTAMP: "@",
        W3C: "yy-mm-dd",
        _ticksTo1970: 1e7 * 60 * 60 * 24 * (718685 + Math.floor(492.5) - Math.floor(19.7) + Math.floor(4.925)),
        formatDate: function (e, t, n) {
            if (!t) return "";
            var r, i = (n ? n.dayNamesShort : null) || this._defaults.dayNamesShort,
                s = (n ? n.dayNames : null) || this._defaults.dayNames,
                o = (n ? n.monthNamesShort : null) || this._defaults.monthNamesShort,
                u = (n ? n.monthNames : null) || this._defaults.monthNames,
                a = function (t) {
                    var n = r + 1 < e.length && e.charAt(r + 1) === t;
                    return n && r++, n
                },
                f = function (e, t, n) {
                    var r = "" + t;
                    if (a(e))
                        for (; r.length < n;) r = "0" + r;
                    return r
                },
                l = function (e, t, n, r) {
                    return a(e) ? r[t] : n[t]
                },
                c = "",
                h = !1;
            if (t)
                for (r = 0; r < e.length; r++)
                    if (h) "'" !== e.charAt(r) || a("'") ? c += e.charAt(r) : h = !1;
                    else switch (e.charAt(r)) {
                    case "d":
                        c += f("d", t.getDate(), 2);
                        break;
                    case "D":
                        c += l("D", t.getDay(), i, s);
                        break;
                    case "o":
                        c += f("o", Math.round((new Date(t.getFullYear(), t.getMonth(), t.getDate()).getTime() - new Date(t.getFullYear(), 0, 0).getTime()) / 864e5), 3);
                        break;
                    case "m":
                        c += f("m", t.getMonth() + 1, 2);
                        break;
                    case "M":
                        c += l("M", t.getMonth(), o, u);
                        break;
                    case "y":
                        c += a("y") ? t.getFullYear() : (t.getYear() % 100 < 10 ? "0" : "") + t.getYear() % 100;
                        break;
                    case "@":
                        c += t.getTime();
                        break;
                    case "!":
                        c += 1e4 * t.getTime() + this._ticksTo1970;
                        break;
                    case "'":
                        a("'") ? c += "'" : h = !0;
                        break;
                    default:
                        c += e.charAt(r)
                    }
                    return c
        },
        _possibleChars: function (e) {
            var t, n = "",
                r = !1,
                i = function (n) {
                    var r = t + 1 < e.length && e.charAt(t + 1) === n;
                    return r && t++, r
                };
            for (t = 0; t < e.length; t++)
                if (r) "'" !== e.charAt(t) || i("'") ? n += e.charAt(t) : r = !1;
                else switch (e.charAt(t)) {
                case "d":
                case "m":
                case "y":
                case "@":
                    n += "0123456789";
                    break;
                case "D":
                case "M":
                    return null;
                case "'":
                    i("'") ? n += "'" : r = !0;
                    break;
                default:
                    n += e.charAt(t)
                }
                return n
        },
        _get: function (e, n) {
            return e.settings[n] !== t ? e.settings[n] : this._defaults[n]
        },
        _setDateFromField: function (e, t) {
            if (e.input.val() !== e.lastVal) {
                var n = this._get(e, "dateFormat"),
                    r = e.lastVal = e.input ? e.input.val() : null,
                    i = this._getDefaultDate(e),
                    s = i,
                    o = this._getFormatConfig(e);
                try {
                    s = this.parseDate(n, r, o) || i
                } catch (u) {
                    r = t ? "" : r
                }
                e.selectedDay = s.getDate(), e.drawMonth = e.selectedMonth = s.getMonth(), e.drawYear = e.selectedYear = s.getFullYear(), e.currentDay = r ? s.getDate() : 0, e.currentMonth = r ? s.getMonth() : 0, e.currentYear = r ? s.getFullYear() : 0, this._adjustInstDate(e)
            }
        },
        _getDefaultDate: function (e) {
            return this._restrictMinMax(e, this._determineDate(e, this._get(e, "defaultDate"), new Date))
        },
        _determineDate: function (t, n, r) {
            var i = function (e) {
                    var t = new Date;
                    return t.setDate(t.getDate() + e), t
                },
                s = function (n) {
                    try {
                        return e.datepicker.parseDate(e.datepicker._get(t, "dateFormat"), n, e.datepicker._getFormatConfig(t))
                    } catch (r) {}
                    for (var i = (n.toLowerCase().match(/^c/) ? e.datepicker._getDate(t) : null) || new Date, s = i.getFullYear(), o = i.getMonth(), u = i.getDate(), a = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, f = a.exec(n); f;) {
                        switch (f[2] || "d") {
                        case "d":
                        case "D":
                            u += parseInt(f[1], 10);
                            break;
                        case "w":
                        case "W":
                            u += 7 * parseInt(f[1], 10);
                            break;
                        case "m":
                        case "M":
                            o += parseInt(f[1], 10), u = Math.min(u, e.datepicker._getDaysInMonth(s, o));
                            break;
                        case "y":
                        case "Y":
                            s += parseInt(f[1], 10), u = Math.min(u, e.datepicker._getDaysInMonth(s, o))
                        }
                        f = a.exec(n)
                    }
                    return new Date(s, o, u)
                },
                o = null == n || "" === n ? r : "string" == typeof n ? s(n) : "number" == typeof n ? isNaN(n) ? r : i(n) : new Date(n.getTime());
            return o = o && "Invalid Date" === o.toString() ? r : o, o && (o.setHours(0), o.setMinutes(0), o.setSeconds(0), o.setMilliseconds(0)), this._daylightSavingAdjust(o)
        },
        _daylightSavingAdjust: function (e) {
            return e ? (e.setHours(e.getHours() > 12 ? e.getHours() + 2 : 0), e) : null
        },
        _setDate: function (e, t, n) {
            var r = !t,
                i = e.selectedMonth,
                s = e.selectedYear,
                o = this._restrictMinMax(e, this._determineDate(e, t, new Date));
            e.selectedDay = e.currentDay = o.getDate(), e.drawMonth = e.selectedMonth = e.currentMonth = o.getMonth(), e.drawYear = e.selectedYear = e.currentYear = o.getFullYear(), (i !== e.selectedMonth || s !== e.selectedYear) && !n && this._notifyChange(e), this._adjustInstDate(e), e.input && e.input.val(r ? "" : this._formatDate(e))
        },
        _getDate: function (e) {
            var t = !e.currentYear || e.input && "" === e.input.val() ? null : this._daylightSavingAdjust(new Date(e.currentYear, e.currentMonth, e.currentDay));
            return t
        },
        _attachHandlers: function (t) {
            var n = this._get(t, "stepMonths"),
                i = "#" + t.id.replace(/\\\\/g, "\\");
            t.dpDiv.find("[data-handler]").map(function () {
                var t = {
                    prev: function () {
                        window["DP_jQuery_" + r].datepicker._adjustDate(i, -n, "M")
                    },
                    next: function () {
                        window["DP_jQuery_" + r].datepicker._adjustDate(i, +n, "M")
                    },
                    hide: function () {
                        window["DP_jQuery_" + r].datepicker._hideDatepicker()
                    },
                    today: function () {
                        window["DP_jQuery_" + r].datepicker._gotoToday(i)
                    },
                    selectDay: function () {
                        return window["DP_jQuery_" + r].datepicker._selectDay(i, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this), !1
                    },
                    selectMonth: function () {
                        return window["DP_jQuery_" + r].datepicker._selectMonthYear(i, this, "M"), !1
                    },
                    selectYear: function () {
                        return window["DP_jQuery_" + r].datepicker._selectMonthYear(i, this, "Y"), !1
                    }
                };
                e(this).bind(this.getAttribute("data-event"), t[this.getAttribute("data-handler")])
            })
        },
        _generateHTML: function (e) {
            var t, n, r, i, s, o, u, a, f, l, c, h, p, d, v, m, g, y, b, w, E, S, x, T, N, C, k, L, A, O, M, _, D, P, H, B, j, F, I, q = new Date,
                R = this._daylightSavingAdjust(new Date(q.getFullYear(), q.getMonth(), q.getDate())),
                U = this._get(e, "isRTL"),
                z = this._get(e, "showButtonPanel"),
                W = this._get(e, "hideIfNoPrevNext"),
                X = this._get(e, "navigationAsDateFormat"),
                V = this._getNumberOfMonths(e),
                $ = this._get(e, "showCurrentAtPos"),
                J = this._get(e, "stepMonths"),
                K = 1 !== V[0] || 1 !== V[1],
                Q = this._daylightSavingAdjust(e.currentDay ? new Date(e.currentYear, e.currentMonth, e.currentDay) : new Date(9999, 9, 9)),
                G = this._getMinMaxDate(e, "min"),
                Y = this._getMinMaxDate(e, "max"),
                Z = e.drawMonth - $,
                et = e.drawYear;
            if (0 > Z && (Z += 12, et--), Y)
                for (t = this._daylightSavingAdjust(new Date(Y.getFullYear(), Y.getMonth() - V[0] * V[1] + 1, Y.getDate())), t = G && G > t ? G : t; this._daylightSavingAdjust(new Date(et, Z, 1)) > t;) Z--, 0 > Z && (Z = 11, et--);
            for (e.drawMonth = Z, e.drawYear = et, n = this._get(e, "prevText"), n = X ? this.formatDate(n, this._daylightSavingAdjust(new Date(et, Z - J, 1)), this._getFormatConfig(e)) : n, r = this._canAdjustMonth(e, -1, et, Z) ? "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='" + n + "'><span class='ui-icon ui-icon-circle-triangle-" + (U ? "e" : "w") + "'>" + n + "</span></a>" : W ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='" + n + "'><span class='ui-icon ui-icon-circle-triangle-" + (U ? "e" : "w") + "'>" + n + "</span></a>", i = this._get(e, "nextText"), i = X ? this.formatDate(i, this._daylightSavingAdjust(new Date(et, Z + J, 1)), this._getFormatConfig(e)) : i, s = this._canAdjustMonth(e, 1, et, Z) ? "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='" + i + "'><span class='ui-icon ui-icon-circle-triangle-" + (U ? "w" : "e") + "'>" + i + "</span></a>" : W ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='" + i + "'><span class='ui-icon ui-icon-circle-triangle-" + (U ? "w" : "e") + "'>" + i + "</span></a>", o = this._get(e, "currentText"), u = this._get(e, "gotoCurrent") && e.currentDay ? Q : R, o = X ? this.formatDate(o, u, this._getFormatConfig(e)) : o, a = e.inline ? "" : "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" + this._get(e, "closeText") + "</button>", f = z ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (U ? a : "") + (this._isInRange(e, u) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>" + o + "</button>" : "") + (U ? "" : a) + "</div>" : "", l = parseInt(this._get(e, "firstDay"), 10), l = isNaN(l) ? 0 : l, c = this._get(e, "showWeek"), h = this._get(e, "dayNames"), p = this._get(e, "dayNamesMin"), d = this._get(e, "monthNames"), v = this._get(e, "monthNamesShort"), m = this._get(e, "beforeShowDay"), g = this._get(e, "showOtherMonths"), y = this._get(e, "selectOtherMonths"), b = this._getDefaultDate(e), w = "", E, S = 0; S < V[0]; S++) {
                for (x = "", this.maxRows = 4, T = 0; T < V[1]; T++) {
                    if (N = this._daylightSavingAdjust(new Date(et, Z, e.selectedDay)), C = " ui-corner-all", k = "", K) {
                        if (k += "<div class='ui-datepicker-group", V[1] > 1) switch (T) {
                        case 0:
                            k += " ui-datepicker-group-first", C = " ui-corner-" + (U ? "right" : "left");
                            break;
                        case V[1] - 1:
                            k += " ui-datepicker-group-last", C = " ui-corner-" + (U ? "left" : "right");
                            break;
                        default:
                            k += " ui-datepicker-group-middle", C = ""
                        }
                        k += "'>"
                    }
                    for (k += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + C + "'>" + (/all|left/.test(C) && 0 === S ? U ? s : r : "") + (/all|right/.test(C) && 0 === S ? U ? r : s : "") + this._generateMonthYearHeader(e, Z, et, G, Y, S > 0 || T > 0, d, v) + "</div><table class='ui-datepicker-calendar'><thead><tr>", L = c ? "<th class='ui-datepicker-week-col'>" + this._get(e, "weekHeader") + "</th>" : "", E = 0; 7 > E; E++) A = (E + l) % 7, L += "<th" + ((E + l + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + "><span title='" + h[A] + "'>" + p[A] + "</span></th>";
                    for (k += L + "</tr></thead><tbody>", O = this._getDaysInMonth(et, Z), et === e.selectedYear && Z === e.selectedMonth && (e.selectedDay = Math.min(e.selectedDay, O)), M = (this._getFirstDayOfMonth(et, Z) - l + 7) % 7, _ = Math.ceil((M + O) / 7), D = K ? this.maxRows > _ ? this.maxRows : _ : _, this.maxRows = D, P = this._daylightSavingAdjust(new Date(et, Z, 1 - M)), H = 0; D > H; H++) {
                        for (k += "<tr>", B = c ? "<td class='ui-datepicker-week-col'>" + this._get(e, "calculateWeek")(P) + "</td>" : "", E = 0; 7 > E; E++) j = m ? m.apply(e.input ? e.input[0] : null, [P]) : [!0, ""], F = P.getMonth() !== Z, I = F && !y || !j[0] || G && G > P || Y && P > Y, B += "<td class='" + ((E + l + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + (F ? " ui-datepicker-other-month" : "") + (P.getTime() === N.getTime() && Z === e.selectedMonth && e._keyEvent || b.getTime() === P.getTime() && b.getTime() === N.getTime() ? " " + this._dayOverClass : "") + (I ? " " + this._unselectableClass + " ui-state-disabled" : "") + (F && !g ? "" : " " + j[1] + (P.getTime() === Q.getTime() ? " " + this._currentClass : "") + (P.getTime() === R.getTime() ? " ui-datepicker-today" : "")) + "'" + (F && !g || !j[2] ? "" : " title='" + j[2].replace(/'/g, "&#39;") + "'") + (I ? "" : " data-handler='selectDay' data-event='click' data-month='" + P.getMonth() + "' data-year='" + P.getFullYear() + "'") + ">" + (F && !g ? "&#xa0;" : I ? "<span class='ui-state-default'>" + P.getDate() + "</span>" : "<a class='ui-state-default" + (P.getTime() === R.getTime() ? " ui-state-highlight" : "") + (P.getTime() === Q.getTime() ? " ui-state-active" : "") + (F ? " ui-priority-secondary" : "") + "' href='#'>" + P.getDate() + "</a>") + "</td>", P.setDate(P.getDate() + 1), P = this._daylightSavingAdjust(P);
                        k += B + "</tr>"
                    }
                    Z++, Z > 11 && (Z = 0, et++), k += "</tbody></table>" + (K ? "</div>" + (V[0] > 0 && T === V[1] - 1 ? "<div class='ui-datepicker-row-break'></div>" : "") : ""), x += k
                }
                w += x
            }
            return w += f, e._keyEvent = !1, w
        },
        _generateMonthYearHeader: function (e, t, n, r, i, s, o, u) {
            var a, f, l, c, h, p, d, v, m = this._get(e, "changeMonth"),
                g = this._get(e, "changeYear"),
                y = this._get(e, "showMonthAfterYear"),
                b = "<div class='ui-datepicker-title'>",
                w = "";
            if (s || !m) w += "<span class='ui-datepicker-month'>" + o[t] + "</span>";
            else {
                for (a = r && r.getFullYear() === n, f = i && i.getFullYear() === n, w += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>", l = 0; 12 > l; l++)(!a || l >= r.getMonth()) && (!f || l <= i.getMonth()) && (w += "<option value='" + l + "'" + (l === t ? " selected='selected'" : "") + ">" + u[l] + "</option>");
                w += "</select>"
            } if (y || (b += w + (!s && m && g ? "" : "&#xa0;")), !e.yearshtml)
                if (e.yearshtml = "", s || !g) b += "<span class='ui-datepicker-year'>" + n + "</span>";
                else {
                    for (c = this._get(e, "yearRange").split(":"), h = (new Date).getFullYear(), p = function (e) {
                        var t = e.match(/c[+\-].*/) ? n + parseInt(e.substring(1), 10) : e.match(/[+\-].*/) ? h + parseInt(e, 10) : parseInt(e, 10);
                        return isNaN(t) ? h : t
                    }, d = p(c[0]), v = Math.max(d, p(c[1] || "")), d = r ? Math.max(d, r.getFullYear()) : d, v = i ? Math.min(v, i.getFullYear()) : v, e.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>"; v >= d; d++) e.yearshtml += "<option value='" + d + "'" + (d === n ? " selected='selected'" : "") + ">" + d + "</option>";
                    e.yearshtml += "</select>", b += e.yearshtml, e.yearshtml = null
                }
            return b += this._get(e, "yearSuffix"), y && (b += (!s && m && g ? "" : "&#xa0;") + w), b += "</div>"
        },
        _adjustInstDate: function (e, t, n) {
            var r = e.drawYear + ("Y" === n ? t : 0),
                i = e.drawMonth + ("M" === n ? t : 0),
                s = Math.min(e.selectedDay, this._getDaysInMonth(r, i)) + ("D" === n ? t : 0),
                o = this._restrictMinMax(e, this._daylightSavingAdjust(new Date(r, i, s)));
            e.selectedDay = o.getDate(), e.drawMonth = e.selectedMonth = o.getMonth(), e.drawYear = e.selectedYear = o.getFullYear(), ("M" === n || "Y" === n) && this._notifyChange(e)
        },
        _restrictMinMax: function (e, t) {
            var n = this._getMinMaxDate(e, "min"),
                r = this._getMinMaxDate(e, "max"),
                i = n && n > t ? n : t;
            return r && i > r ? r : i
        },
        _notifyChange: function (e) {
            var t = this._get(e, "onChangeMonthYear");
            t && t.apply(e.input ? e.input[0] : null, [e.selectedYear, e.selectedMonth + 1, e])
        },
        _getNumberOfMonths: function (e) {
            var t = this._get(e, "numberOfMonths");
            return null == t ? [1, 1] : "number" == typeof t ? [1, t] : t
        },
        _getMinMaxDate: function (e, t) {
            return this._determineDate(e, this._get(e, t + "Date"), null)
        },
        _getDaysInMonth: function (e, t) {
            return 32 - this._daylightSavingAdjust(new Date(e, t, 32)).getDate()
        },
        _getFirstDayOfMonth: function (e, t) {
            return new Date(e, t, 1).getDay()
        },
        _canAdjustMonth: function (e, t, n, r) {
            var i = this._getNumberOfMonths(e),
                s = this._daylightSavingAdjust(new Date(n, r + (0 > t ? t : i[0] * i[1]), 1));
            return 0 > t && s.setDate(this._getDaysInMonth(s.getFullYear(), s.getMonth())), this._isInRange(e, s)
        },
        _isInRange: function (e, t) {
            var n, r, i = this._getMinMaxDate(e, "min"),
                s = this._getMinMaxDate(e, "max"),
                o = null,
                u = null,
                a = this._get(e, "yearRange");
            return a && (n = a.split(":"), r = (new Date).getFullYear(), o = parseInt(n[0], 10), u = parseInt(n[1], 10), n[0].match(/[+\-].*/) && (o += r), n[1].match(/[+\-].*/) && (u += r)), (!i || t.getTime() >= i.getTime()) && (!s || t.getTime() <= s.getTime()) && (!o || t.getFullYear() >= o) && (!u || t.getFullYear() <= u)
        },
        _getFormatConfig: function (e) {
            var t = this._get(e, "shortYearCutoff");
            return t = "string" != typeof t ? t : (new Date).getFullYear() % 100 + parseInt(t, 10), {
                shortYearCutoff: t,
                dayNamesShort: this._get(e, "dayNamesShort"),
                dayNames: this._get(e, "dayNames"),
                monthNamesShort: this._get(e, "monthNamesShort"),
                monthNames: this._get(e, "monthNames")
            }
        },
        _formatDate: function (e, t, n, r) {
            t || (e.currentDay = e.selectedDay, e.currentMonth = e.selectedMonth, e.currentYear = e.selectedYear);
            var i = t ? "object" == typeof t ? t : this._daylightSavingAdjust(new Date(r, n, t)) : this._daylightSavingAdjust(new Date(e.currentYear, e.currentMonth, e.currentDay));
            return this.formatDate(this._get(e, "dateFormat"), i, this._getFormatConfig(e))
        }
    }), e.fn.datepicker = function (t) {
        if (!this.length) return this;
        e.datepicker.initialized || (e(document).mousedown(e.datepicker._checkExternalClick), e.datepicker.initialized = !0), 0 === e("#" + e.datepicker._mainDivId).length && e("body").append(e.datepicker.dpDiv);
        var n = Array.prototype.slice.call(arguments, 1);
        return "string" != typeof t || "isDisabled" !== t && "getDate" !== t && "widget" !== t ? "option" === t && 2 === arguments.length && "string" == typeof arguments[1] ? e.datepicker["_" + t + "Datepicker"].apply(e.datepicker, [this[0]].concat(n)) : this.each(function () {
            "string" == typeof t ? e.datepicker["_" + t + "Datepicker"].apply(e.datepicker, [this].concat(n)) : e.datepicker._attachDatepicker(this, t)
        }) : e.datepicker["_" + t + "Datepicker"].apply(e.datepicker, [this[0]].concat(n))
    }, e.datepicker = new s, e.datepicker.initialized = !1, e.datepicker.uuid = (new Date).getTime(), e.datepicker.version = "1.10.1", window["DP_jQuery_" + r] = e
}(jQuery),
function (e) {
    var n = {
            buttons: !0,
            height: !0,
            maxHeight: !0,
            maxWidth: !0,
            minHeight: !0,
            minWidth: !0,
            width: !0
        },
        r = {
            maxHeight: !0,
            maxWidth: !0,
            minHeight: !0,
            minWidth: !0
        };
    e.widget("ui.dialog", {
        version: "1.10.1",
        options: {
            appendTo: "body",
            autoOpen: !0,
            buttons: [],
            closeOnEscape: !0,
            closeText: "close",
            dialogClass: "",
            draggable: !0,
            hide: null,
            height: "auto",
            maxHeight: null,
            maxWidth: null,
            minHeight: 150,
            minWidth: 150,
            modal: !1,
            position: {
                my: "center",
                at: "center",
                of: window,
                collision: "fit",
                using: function (t) {
                    var n = e(this).css(t).offset().top;
                    0 > n && e(this).css("top", t.top - n)
                }
            },
            resizable: !0,
            show: null,
            title: null,
            width: 300,
            beforeClose: null,
            close: null,
            drag: null,
            dragStart: null,
            dragStop: null,
            focus: null,
            open: null,
            resize: null,
            resizeStart: null,
            resizeStop: null
        },
        _create: function () {
            this.originalCss = {
                display: this.element[0].style.display,
                width: this.element[0].style.width,
                minHeight: this.element[0].style.minHeight,
                maxHeight: this.element[0].style.maxHeight,
                height: this.element[0].style.height
            }, this.originalPosition = {
                parent: this.element.parent(),
                index: this.element.parent().children().index(this.element)
            }, this.originalTitle = this.element.attr("title"), this.options.title = this.options.title || this.originalTitle, this._createWrapper(), this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog), this._createTitlebar(), this._createButtonPane(), this.options.draggable && e.fn.draggable && this._makeDraggable(), this.options.resizable && e.fn.resizable && this._makeResizable(), this._isOpen = !1
        },
        _init: function () {
            this.options.autoOpen && this.open()
        },
        _appendTo: function () {
            var t = this.options.appendTo;
            return t && (t.jquery || t.nodeType) ? e(t) : this.document.find(t || "body").eq(0)
        },
        _destroy: function () {
            var e, t = this.originalPosition;
            this._destroyOverlay(), this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(), this.uiDialog.stop(!0, !0).remove(), this.originalTitle && this.element.attr("title", this.originalTitle), e = t.parent.children().eq(t.index), e.length && e[0] !== this.element[0] ? e.before(this.element) : t.parent.append(this.element)
        },
        widget: function () {
            return this.uiDialog
        },
        disable: e.noop,
        enable: e.noop,
        close: function (t) {
            var n = this;
            this._isOpen && this._trigger("beforeClose", t) !== !1 && (this._isOpen = !1, this._destroyOverlay(), this.opener.filter(":focusable").focus().length || e(this.document[0].activeElement).blur(), this._hide(this.uiDialog, this.options.hide, function () {
                n._trigger("close", t)
            }))
        },
        isOpen: function () {
            return this._isOpen
        },
        moveToTop: function () {
            this._moveToTop()
        },
        _moveToTop: function (e, t) {
            var n = !!this.uiDialog.nextAll(":visible").insertBefore(this.uiDialog).length;
            return n && !t && this._trigger("focus", e), n
        },
        open: function () {
            var t = this;
            return this._isOpen ? (this._moveToTop() && this._focusTabbable(), void 0) : (this._isOpen = !0, this.opener = e(this.document[0].activeElement), this._size(), this._position(), this._createOverlay(), this._moveToTop(null, !0), this._show(this.uiDialog, this.options.show, function () {
                t._focusTabbable(), t._trigger("focus")
            }), this._trigger("open"), void 0)
        },
        _focusTabbable: function () {
            var e = this.element.find("[autofocus]");
            e.length || (e = this.element.find(":tabbable")), e.length || (e = this.uiDialogButtonPane.find(":tabbable")), e.length || (e = this.uiDialogTitlebarClose.filter(":tabbable")), e.length || (e = this.uiDialog), e.eq(0).focus()
        },
        _keepFocus: function (t) {
            function n() {
                var t = this.document[0].activeElement,
                    n = this.uiDialog[0] === t || e.contains(this.uiDialog[0], t);
                n || this._focusTabbable()
            }
            t.preventDefault(), n.call(this), this._delay(n)
        },
        _createWrapper: function () {
            this.uiDialog = e("<div>").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " + this.options.dialogClass).hide().attr({
                tabIndex: -1,
                role: "dialog"
            }).appendTo(this._appendTo()), this._on(this.uiDialog, {
                keydown: function (t) {
                    if (this.options.closeOnEscape && !t.isDefaultPrevented() && t.keyCode && t.keyCode === e.ui.keyCode.ESCAPE) return t.preventDefault(), this.close(t), void 0;
                    if (t.keyCode === e.ui.keyCode.TAB) {
                        var n = this.uiDialog.find(":tabbable"),
                            r = n.filter(":first"),
                            i = n.filter(":last");
                        t.target !== i[0] && t.target !== this.uiDialog[0] || t.shiftKey ? (t.target === r[0] || t.target === this.uiDialog[0]) && t.shiftKey && (i.focus(1), t.preventDefault()) : (r.focus(1), t.preventDefault())
                    }
                },
                mousedown: function (e) {
                    this._moveToTop(e) && this._focusTabbable()
                }
            }), this.element.find("[aria-describedby]").length || this.uiDialog.attr({
                "aria-describedby": this.element.uniqueId().attr("id")
            })
        },
        _createTitlebar: function () {
            var t;
            this.uiDialogTitlebar = e("<div>").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog), this._on(this.uiDialogTitlebar, {
                mousedown: function (t) {
                    e(t.target).closest(".ui-dialog-titlebar-close") || this.uiDialog.focus()
                }
            }), this.uiDialogTitlebarClose = e("<button></button>").button({
                label: this.options.closeText,
                icons: {
                    primary: "ui-icon-closethick"
                },
                text: !1
            }).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar), this._on(this.uiDialogTitlebarClose, {
                click: function (e) {
                    e.preventDefault(), this.close(e)
                }
            }), t = e("<span>").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar), this._title(t), this.uiDialog.attr({
                "aria-labelledby": t.attr("id")
            })
        },
        _title: function (e) {
            this.options.title || e.html("&#160;"), e.text(this.options.title)
        },
        _createButtonPane: function () {
            this.uiDialogButtonPane = e("<div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"), this.uiButtonSet = e("<div>").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane), this._createButtons()
        },
        _createButtons: function () {
            var t = this,
                n = this.options.buttons;
            return this.uiDialogButtonPane.remove(), this.uiButtonSet.empty(), e.isEmptyObject(n) || e.isArray(n) && !n.length ? (this.uiDialog.removeClass("ui-dialog-buttons"), void 0) : (e.each(n, function (n, r) {
                var i, s;
                r = e.isFunction(r) ? {
                    click: r,
                    text: n
                } : r, r = e.extend({
                    type: "button"
                }, r), i = r.click, r.click = function () {
                    i.apply(t.element[0], arguments)
                }, s = {
                    icons: r.icons,
                    text: r.showText
                }, delete r.icons, delete r.showText, e("<button></button>", r).button(s).appendTo(t.uiButtonSet)
            }), this.uiDialog.addClass("ui-dialog-buttons"), this.uiDialogButtonPane.appendTo(this.uiDialog), void 0)
        },
        _makeDraggable: function () {
            function r(e) {
                return {
                    position: e.position,
                    offset: e.offset
                }
            }
            var t = this,
                n = this.options;
            this.uiDialog.draggable({
                cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
                handle: ".ui-dialog-titlebar",
                containment: "document",
                start: function (n, i) {
                    e(this).addClass("ui-dialog-dragging"), t._blockFrames(), t._trigger("dragStart", n, r(i))
                },
                drag: function (e, n) {
                    t._trigger("drag", e, r(n))
                },
                stop: function (i, s) {
                    n.position = [s.position.left - t.document.scrollLeft(), s.position.top - t.document.scrollTop()], e(this).removeClass("ui-dialog-dragging"), t._unblockFrames(), t._trigger("dragStop", i, r(s))
                }
            })
        },
        _makeResizable: function () {
            function o(e) {
                return {
                    originalPosition: e.originalPosition,
                    originalSize: e.originalSize,
                    position: e.position,
                    size: e.size
                }
            }
            var t = this,
                n = this.options,
                r = n.resizable,
                i = this.uiDialog.css("position"),
                s = "string" == typeof r ? r : "n,e,s,w,se,sw,ne,nw";
            this.uiDialog.resizable({
                cancel: ".ui-dialog-content",
                containment: "document",
                alsoResize: this.element,
                maxWidth: n.maxWidth,
                maxHeight: n.maxHeight,
                minWidth: n.minWidth,
                minHeight: this._minHeight(),
                handles: s,
                start: function (n, r) {
                    e(this).addClass("ui-dialog-resizing"), t._blockFrames(), t._trigger("resizeStart", n, o(r))
                },
                resize: function (e, n) {
                    t._trigger("resize", e, o(n))
                },
                stop: function (r, i) {
                    n.height = e(this).height(), n.width = e(this).width(), e(this).removeClass("ui-dialog-resizing"), t._unblockFrames(), t._trigger("resizeStop", r, o(i))
                }
            }).css("position", i)
        },
        _minHeight: function () {
            var e = this.options;
            return "auto" === e.height ? e.minHeight : Math.min(e.minHeight, e.height)
        },
        _position: function () {
            var e = this.uiDialog.is(":visible");
            e || this.uiDialog.show(), this.uiDialog.position(this.options.position), e || this.uiDialog.hide()
        },
        _setOptions: function (t) {
            var i = this,
                s = !1,
                o = {};
            e.each(t, function (e, t) {
                i._setOption(e, t), e in n && (s = !0), e in r && (o[e] = t)
            }), s && (this._size(), this._position()), this.uiDialog.is(":data(ui-resizable)") && this.uiDialog.resizable("option", o)
        },
        _setOption: function (e, t) {
            var n, r, i = this.uiDialog;
            "dialogClass" === e && i.removeClass(this.options.dialogClass).addClass(t), "disabled" !== e && (this._super(e, t), "appendTo" === e && this.uiDialog.appendTo(this._appendTo()), "buttons" === e && this._createButtons(), "closeText" === e && this.uiDialogTitlebarClose.button({
                label: "" + t
            }), "draggable" === e && (n = i.is(":data(ui-draggable)"), n && !t && i.draggable("destroy"), !n && t && this._makeDraggable()), "position" === e && this._position(), "resizable" === e && (r = i.is(":data(ui-resizable)"), r && !t && i.resizable("destroy"), r && "string" == typeof t && i.resizable("option", "handles", t), !r && t !== !1 && this._makeResizable()), "title" === e && this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))
        },
        _size: function () {
            var e, t, n, r = this.options;
            this.element.show().css({
                width: "auto",
                minHeight: 0,
                maxHeight: "none",
                height: 0
            }), r.minWidth > r.width && (r.width = r.minWidth), e = this.uiDialog.css({
                height: "auto",
                width: r.width
            }).outerHeight(), t = Math.max(0, r.minHeight - e), n = "number" == typeof r.maxHeight ? Math.max(0, r.maxHeight - e) : "none", "auto" === r.height ? this.element.css({
                minHeight: t,
                maxHeight: n,
                height: "auto"
            }) : this.element.height(Math.max(0, r.height - e)), this.uiDialog.is(":data(ui-resizable)") && this.uiDialog.resizable("option", "minHeight", this._minHeight())
        },
        _blockFrames: function () {
            this.iframeBlocks = this.document.find("iframe").map(function () {
                var t = e(this);
                return e("<div>").css({
                    position: "absolute",
                    width: t.outerWidth(),
                    height: t.outerHeight()
                }).appendTo(t.parent()).offset(t.offset())[0]
            })
        },
        _unblockFrames: function () {
            this.iframeBlocks && (this.iframeBlocks.remove(), delete this.iframeBlocks)
        },
        _createOverlay: function () {
            this.options.modal && (e.ui.dialog.overlayInstances || this._delay(function () {
                e.ui.dialog.overlayInstances && this.document.bind("focusin.dialog", function (t) {
                    !e(t.target).closest(".ui-dialog").length && !e(t.target).closest(".ui-datepicker").length && (t.preventDefault(), e(".ui-dialog:visible:last .ui-dialog-content").data("ui-dialog")._focusTabbable())
                })
            }), this.overlay = e("<div>").addClass("ui-widget-overlay ui-front").appendTo(this._appendTo()), this._on(this.overlay, {
                mousedown: "_keepFocus"
            }), e.ui.dialog.overlayInstances++)
        },
        _destroyOverlay: function () {
            this.options.modal && this.overlay && (e.ui.dialog.overlayInstances--, e.ui.dialog.overlayInstances || this.document.unbind("focusin.dialog"), this.overlay.remove(), this.overlay = null)
        }
    }), e.ui.dialog.overlayInstances = 0, e.uiBackCompat !== !1 && e.widget("ui.dialog", e.ui.dialog, {
        _position: function () {
            var i, t = this.options.position,
                n = [],
                r = [0, 0];
            t ? (("string" == typeof t || "object" == typeof t && "0" in t) && (n = t.split ? t.split(" ") : [t[0], t[1]], 1 === n.length && (n[1] = n[0]), e.each(["left", "top"], function (e, t) {
                +n[e] === n[e] && (r[e] = n[e], n[e] = t)
            }), t = {
                my: n[0] + (r[0] < 0 ? r[0] : "+" + r[0]) + " " + n[1] + (r[1] < 0 ? r[1] : "+" + r[1]),
                at: n.join(" ")
            }), t = e.extend({}, e.ui.dialog.prototype.options.position, t)) : t = e.ui.dialog.prototype.options.position, i = this.uiDialog.is(":visible"), i || this.uiDialog.show(), this.uiDialog.position(t), i || this.uiDialog.hide()
        }
    })
}(jQuery),
function (e) {
    e.widget("ui.draggable", e.ui.mouse, {
        version: "1.10.1",
        widgetEventPrefix: "drag",
        options: {
            addClasses: !0,
            appendTo: "parent",
            axis: !1,
            connectToSortable: !1,
            containment: !1,
            cursor: "auto",
            cursorAt: !1,
            grid: !1,
            handle: !1,
            helper: "original",
            iframeFix: !1,
            opacity: !1,
            refreshPositions: !1,
            revert: !1,
            revertDuration: 500,
            scope: "default",
            scroll: !0,
            scrollSensitivity: 20,
            scrollSpeed: 20,
            snap: !1,
            snapMode: "both",
            snapTolerance: 20,
            stack: !1,
            zIndex: !1,
            drag: null,
            start: null,
            stop: null
        },
        _create: function () {
            "original" === this.options.helper && !/^(?:r|a|f)/.test(this.element.css("position")) && (this.element[0].style.position = "relative"), this.options.addClasses && this.element.addClass("ui-draggable"), this.options.disabled && this.element.addClass("ui-draggable-disabled"), this._mouseInit()
        },
        _destroy: function () {
            this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"), this._mouseDestroy()
        },
        _mouseCapture: function (t) {
            var n = this.options;
            return this.helper || n.disabled || e(t.target).closest(".ui-resizable-handle").length > 0 ? !1 : (this.handle = this._getHandle(t), this.handle ? (e(n.iframeFix === !0 ? "iframe" : n.iframeFix).each(function () {
                e("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>").css({
                    width: this.offsetWidth + "px",
                    height: this.offsetHeight + "px",
                    position: "absolute",
                    opacity: "0.001",
                    zIndex: 1e3
                }).css(e(this).offset()).appendTo("body")
            }), !0) : !1)
        },
        _mouseStart: function (t) {
            var n = this.options;
            return this.helper = this._createHelper(t), this.helper.addClass("ui-draggable-dragging"), this._cacheHelperProportions(), e.ui.ddmanager && (e.ui.ddmanager.current = this), this._cacheMargins(), this.cssPosition = this.helper.css("position"), this.scrollParent = this.helper.scrollParent(), this.offset = this.positionAbs = this.element.offset(), this.offset = {
                top: this.offset.top - this.margins.top,
                left: this.offset.left - this.margins.left
            }, e.extend(this.offset, {
                click: {
                    left: t.pageX - this.offset.left,
                    top: t.pageY - this.offset.top
                },
                parent: this._getParentOffset(),
                relative: this._getRelativeOffset()
            }), this.originalPosition = this.position = this._generatePosition(t), this.originalPageX = t.pageX, this.originalPageY = t.pageY, n.cursorAt && this._adjustOffsetFromHelper(n.cursorAt), n.containment && this._setContainment(), this._trigger("start", t) === !1 ? (this._clear(), !1) : (this._cacheHelperProportions(), e.ui.ddmanager && !n.dropBehaviour && e.ui.ddmanager.prepareOffsets(this, t), this._mouseDrag(t, !0), e.ui.ddmanager && e.ui.ddmanager.dragStart(this, t), !0)
        },
        _mouseDrag: function (t, n) {
            if (this.position = this._generatePosition(t), this.positionAbs = this._convertPositionTo("absolute"), !n) {
                var r = this._uiHash();
                if (this._trigger("drag", t, r) === !1) return this._mouseUp({}), !1;
                this.position = r.position
            }
            return this.options.axis && "y" === this.options.axis || (this.helper[0].style.left = this.position.left + "px"), this.options.axis && "x" === this.options.axis || (this.helper[0].style.top = this.position.top + "px"), e.ui.ddmanager && e.ui.ddmanager.drag(this, t), !1
        },
        _mouseStop: function (t) {
            var n, r = this,
                i = !1,
                s = !1;
            for (e.ui.ddmanager && !this.options.dropBehaviour && (s = e.ui.ddmanager.drop(this, t)), this.dropped && (s = this.dropped, this.dropped = !1), n = this.element[0]; n && (n = n.parentNode);) n === document && (i = !0);
            return i || "original" !== this.options.helper ? ("invalid" === this.options.revert && !s || "valid" === this.options.revert && s || this.options.revert === !0 || e.isFunction(this.options.revert) && this.options.revert.call(this.element, s) ? e(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function () {
                r._trigger("stop", t) !== !1 && r._clear()
            }) : this._trigger("stop", t) !== !1 && this._clear(), !1) : !1
        },
        _mouseUp: function (t) {
            return e("div.ui-draggable-iframeFix").each(function () {
                this.parentNode.removeChild(this)
            }), e.ui.ddmanager && e.ui.ddmanager.dragStop(this, t), e.ui.mouse.prototype._mouseUp.call(this, t)
        },
        cancel: function () {
            return this.helper.is(".ui-draggable-dragging") ? this._mouseUp({}) : this._clear(), this
        },
        _getHandle: function (t) {
            var n = this.options.handle && e(this.options.handle, this.element).length ? !1 : !0;
            return e(this.options.handle, this.element).find("*").addBack().each(function () {
                this === t.target && (n = !0)
            }), n
        },
        _createHelper: function (t) {
            var n = this.options,
                r = e.isFunction(n.helper) ? e(n.helper.apply(this.element[0], [t])) : "clone" === n.helper ? this.element.clone().removeAttr("id") : this.element;
            return r.parents("body").length || r.appendTo("parent" === n.appendTo ? this.element[0].parentNode : n.appendTo), r[0] !== this.element[0] && !/(fixed|absolute)/.test(r.css("position")) && r.css("position", "absolute"), r
        },
        _adjustOffsetFromHelper: function (t) {
            "string" == typeof t && (t = t.split(" ")), e.isArray(t) && (t = {
                left: +t[0],
                top: +t[1] || 0
            }), "left" in t && (this.offset.click.left = t.left + this.margins.left), "right" in t && (this.offset.click.left = this.helperProportions.width - t.right + this.margins.left), "top" in t && (this.offset.click.top = t.top + this.margins.top), "bottom" in t && (this.offset.click.top = this.helperProportions.height - t.bottom + this.margins.top)
        },
        _getParentOffset: function () {
            this.offsetParent = this.helper.offsetParent();
            var t = this.offsetParent.offset();
            return "absolute" === this.cssPosition && this.scrollParent[0] !== document && e.contains(this.scrollParent[0], this.offsetParent[0]) && (t.left += this.scrollParent.scrollLeft(), t.top += this.scrollParent.scrollTop()), (this.offsetParent[0] === document.body || this.offsetParent[0].tagName && "html" === this.offsetParent[0].tagName.toLowerCase() && e.ui.ie) && (t = {
                top: 0,
                left: 0
            }), {
                top: t.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
                left: t.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
            }
        },
        _getRelativeOffset: function () {
            if ("relative" === this.cssPosition) {
                var e = this.element.position();
                return {
                    top: e.top - (parseInt(this.helper.css("top"), 10) || 0) + this.scrollParent.scrollTop(),
                    left: e.left - (parseInt(this.helper.css("left"), 10) || 0) + this.scrollParent.scrollLeft()
                }
            }
            return {
                top: 0,
                left: 0
            }
        },
        _cacheMargins: function () {
            this.margins = {
                left: parseInt(this.element.css("marginLeft"), 10) || 0,
                top: parseInt(this.element.css("marginTop"), 10) || 0,
                right: parseInt(this.element.css("marginRight"), 10) || 0,
                bottom: parseInt(this.element.css("marginBottom"), 10) || 0
            }
        },
        _cacheHelperProportions: function () {
            this.helperProportions = {
                width: this.helper.outerWidth(),
                height: this.helper.outerHeight()
            }
        },
        _setContainment: function () {
            var t, n, r, i = this.options;
            if ("parent" === i.containment && (i.containment = this.helper[0].parentNode), ("document" === i.containment || "window" === i.containment) && (this.containment = ["document" === i.containment ? 0 : e(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, "document" === i.containment ? 0 : e(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, ("document" === i.containment ? 0 : e(window).scrollLeft()) + e("document" === i.containment ? document : window).width() - this.helperProportions.width - this.margins.left, ("document" === i.containment ? 0 : e(window).scrollTop()) + (e("document" === i.containment ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top]), /^(document|window|parent)$/.test(i.containment) || i.containment.constructor === Array) i.containment.constructor === Array && (this.containment = i.containment);
            else {
                if (n = e(i.containment), r = n[0], !r) return;
                t = "hidden" !== e(r).css("overflow"), this.containment = [(parseInt(e(r).css("borderLeftWidth"), 10) || 0) + (parseInt(e(r).css("paddingLeft"), 10) || 0), (parseInt(e(r).css("borderTopWidth"), 10) || 0) + (parseInt(e(r).css("paddingTop"), 10) || 0), (t ? Math.max(r.scrollWidth, r.offsetWidth) : r.offsetWidth) - (parseInt(e(r).css("borderLeftWidth"), 10) || 0) - (parseInt(e(r).css("paddingRight"), 10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right, (t ? Math.max(r.scrollHeight, r.offsetHeight) : r.offsetHeight) - (parseInt(e(r).css("borderTopWidth"), 10) || 0) - (parseInt(e(r).css("paddingBottom"), 10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom], this.relative_container = n
            }
        },
        _convertPositionTo: function (t, n) {
            n || (n = this.position);
            var r = "absolute" === t ? 1 : -1,
                i = "absolute" !== this.cssPosition || this.scrollParent[0] !== document && e.contains(this.scrollParent[0], this.offsetParent[0]) ? this.scrollParent : this.offsetParent,
                s = /(html|body)/i.test(i[0].tagName);
            return {
                top: n.top + this.offset.relative.top * r + this.offset.parent.top * r - ("fixed" === this.cssPosition ? -this.scrollParent.scrollTop() : s ? 0 : i.scrollTop()) * r,
                left: n.left + this.offset.relative.left * r + this.offset.parent.left * r - ("fixed" === this.cssPosition ? -this.scrollParent.scrollLeft() : s ? 0 : i.scrollLeft()) * r
            }
        },
        _generatePosition: function (t) {
            var n, r, i, s, o = this.options,
                u = "absolute" !== this.cssPosition || this.scrollParent[0] !== document && e.contains(this.scrollParent[0], this.offsetParent[0]) ? this.scrollParent : this.offsetParent,
                a = /(html|body)/i.test(u[0].tagName),
                f = t.pageX,
                l = t.pageY;
            return this.originalPosition && (this.containment && (this.relative_container ? (r = this.relative_container.offset(), n = [this.containment[0] + r.left, this.containment[1] + r.top, this.containment[2] + r.left, this.containment[3] + r.top]) : n = this.containment, t.pageX - this.offset.click.left < n[0] && (f = n[0] + this.offset.click.left), t.pageY - this.offset.click.top < n[1] && (l = n[1] + this.offset.click.top), t.pageX - this.offset.click.left > n[2] && (f = n[2] + this.offset.click.left), t.pageY - this.offset.click.top > n[3] && (l = n[3] + this.offset.click.top)), o.grid && (i = o.grid[1] ? this.originalPageY + Math.round((l - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY, l = n ? i - this.offset.click.top >= n[1] || i - this.offset.click.top > n[3] ? i : i - this.offset.click.top >= n[1] ? i - o.grid[1] : i + o.grid[1] : i, s = o.grid[0] ? this.originalPageX + Math.round((f - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX, f = n ? s - this.offset.click.left >= n[0] || s - this.offset.click.left > n[2] ? s : s - this.offset.click.left >= n[0] ? s - o.grid[0] : s + o.grid[0] : s)), {
                top: l - this.offset.click.top - this.offset.relative.top - this.offset.parent.top + ("fixed" === this.cssPosition ? -this.scrollParent.scrollTop() : a ? 0 : u.scrollTop()),
                left: f - this.offset.click.left - this.offset.relative.left - this.offset.parent.left + ("fixed" === this.cssPosition ? -this.scrollParent.scrollLeft() : a ? 0 : u.scrollLeft())
            }
        },
        _clear: function () {
            this.helper.removeClass("ui-draggable-dragging"), this.helper[0] !== this.element[0] && !this.cancelHelperRemoval && this.helper.remove(), this.helper = null, this.cancelHelperRemoval = !1
        },
        _trigger: function (t, n, r) {
            return r = r || this._uiHash(), e.ui.plugin.call(this, t, [n, r]), "drag" === t && (this.positionAbs = this._convertPositionTo("absolute")), e.Widget.prototype._trigger.call(this, t, n, r)
        },
        plugins: {},
        _uiHash: function () {
            return {
                helper: this.helper,
                position: this.position,
                originalPosition: this.originalPosition,
                offset: this.positionAbs
            }
        }
    }), e.ui.plugin.add("draggable", "connectToSortable", {
        start: function (t, n) {
            var r = e(this).data("ui-draggable"),
                i = r.options,
                s = e.extend({}, n, {
                    item: r.element
                });
            r.sortables = [], e(i.connectToSortable).each(function () {
                var n = e.data(this, "ui-sortable");
                n && !n.options.disabled && (r.sortables.push({
                    instance: n,
                    shouldRevert: n.options.revert
                }), n.refreshPositions(), n._trigger("activate", t, s))
            })
        },
        stop: function (t, n) {
            var r = e(this).data("ui-draggable"),
                i = e.extend({}, n, {
                    item: r.element
                });
            e.each(r.sortables, function () {
                this.instance.isOver ? (this.instance.isOver = 0, r.cancelHelperRemoval = !0, this.instance.cancelHelperRemoval = !1, this.shouldRevert && (this.instance.options.revert = !0), this.instance._mouseStop(t), this.instance.options.helper = this.instance.options._helper, "original" === r.options.helper && this.instance.currentItem.css({
                    top: "auto",
                    left: "auto"
                })) : (this.instance.cancelHelperRemoval = !1, this.instance._trigger("deactivate", t, i))
            })
        },
        drag: function (t, n) {
            var r = e(this).data("ui-draggable"),
                i = this;
            e.each(r.sortables, function () {
                var s = !1,
                    o = this;
                this.instance.positionAbs = r.positionAbs, this.instance.helperProportions = r.helperProportions, this.instance.offset.click = r.offset.click, this.instance._intersectsWith(this.instance.containerCache) && (s = !0, e.each(r.sortables, function () {
                    return this.instance.positionAbs = r.positionAbs, this.instance.helperProportions = r.helperProportions, this.instance.offset.click = r.offset.click, this !== o && this.instance._intersectsWith(this.instance.containerCache) && e.contains(o.instance.element[0], this.instance.element[0]) && (s = !1), s
                })), s ? (this.instance.isOver || (this.instance.isOver = 1, this.instance.currentItem = e(i).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", !0), this.instance.options._helper = this.instance.options.helper, this.instance.options.helper = function () {
                    return n.helper[0]
                }, t.target = this.instance.currentItem[0], this.instance._mouseCapture(t, !0), this.instance._mouseStart(t, !0, !0), this.instance.offset.click.top = r.offset.click.top, this.instance.offset.click.left = r.offset.click.left, this.instance.offset.parent.left -= r.offset.parent.left - this.instance.offset.parent.left, this.instance.offset.parent.top -= r.offset.parent.top - this.instance.offset.parent.top, r._trigger("toSortable", t), r.dropped = this.instance.element, r.currentItem = r.element, this.instance.fromOutside = r), this.instance.currentItem && this.instance._mouseDrag(t)) : this.instance.isOver && (this.instance.isOver = 0, this.instance.cancelHelperRemoval = !0, this.instance.options.revert = !1, this.instance._trigger("out", t, this.instance._uiHash(this.instance)), this.instance._mouseStop(t, !0), this.instance.options.helper = this.instance.options._helper, this.instance.currentItem.remove(), this.instance.placeholder && this.instance.placeholder.remove(), r._trigger("fromSortable", t), r.dropped = !1)
            })
        }
    }), e.ui.plugin.add("draggable", "cursor", {
        start: function () {
            var t = e("body"),
                n = e(this).data("ui-draggable").options;
            t.css("cursor") && (n._cursor = t.css("cursor")), t.css("cursor", n.cursor)
        },
        stop: function () {
            var t = e(this).data("ui-draggable").options;
            t._cursor && e("body").css("cursor", t._cursor)
        }
    }), e.ui.plugin.add("draggable", "opacity", {
        start: function (t, n) {
            var r = e(n.helper),
                i = e(this).data("ui-draggable").options;
            r.css("opacity") && (i._opacity = r.css("opacity")), r.css("opacity", i.opacity)
        },
        stop: function (t, n) {
            var r = e(this).data("ui-draggable").options;
            r._opacity && e(n.helper).css("opacity", r._opacity)
        }
    }), e.ui.plugin.add("draggable", "scroll", {
        start: function () {
            var t = e(this).data("ui-draggable");
            t.scrollParent[0] !== document && "HTML" !== t.scrollParent[0].tagName && (t.overflowOffset = t.scrollParent.offset())
        },
        drag: function (t) {
            var n = e(this).data("ui-draggable"),
                r = n.options,
                i = !1;
            n.scrollParent[0] !== document && "HTML" !== n.scrollParent[0].tagName ? (r.axis && "x" === r.axis || (n.overflowOffset.top + n.scrollParent[0].offsetHeight - t.pageY < r.scrollSensitivity ? n.scrollParent[0].scrollTop = i = n.scrollParent[0].scrollTop + r.scrollSpeed : t.pageY - n.overflowOffset.top < r.scrollSensitivity && (n.scrollParent[0].scrollTop = i = n.scrollParent[0].scrollTop - r.scrollSpeed)), r.axis && "y" === r.axis || (n.overflowOffset.left + n.scrollParent[0].offsetWidth - t.pageX < r.scrollSensitivity ? n.scrollParent[0].scrollLeft = i = n.scrollParent[0].scrollLeft + r.scrollSpeed : t.pageX - n.overflowOffset.left < r.scrollSensitivity && (n.scrollParent[0].scrollLeft = i = n.scrollParent[0].scrollLeft - r.scrollSpeed))) : (r.axis && "x" === r.axis || (t.pageY - e(document).scrollTop() < r.scrollSensitivity ? i = e(document).scrollTop(e(document).scrollTop() - r.scrollSpeed) : e(window).height() - (t.pageY - e(document).scrollTop()) < r.scrollSensitivity && (i = e(document).scrollTop(e(document).scrollTop() + r.scrollSpeed))), r.axis && "y" === r.axis || (t.pageX - e(document).scrollLeft() < r.scrollSensitivity ? i = e(document).scrollLeft(e(document).scrollLeft() - r.scrollSpeed) : e(window).width() - (t.pageX - e(document).scrollLeft()) < r.scrollSensitivity && (i = e(document).scrollLeft(e(document).scrollLeft() + r.scrollSpeed)))), i !== !1 && e.ui.ddmanager && !r.dropBehaviour && e.ui.ddmanager.prepareOffsets(n, t)
        }
    }), e.ui.plugin.add("draggable", "snap", {
        start: function () {
            var t = e(this).data("ui-draggable"),
                n = t.options;
            t.snapElements = [], e(n.snap.constructor !== String ? n.snap.items || ":data(ui-draggable)" : n.snap).each(function () {
                var n = e(this),
                    r = n.offset();
                this !== t.element[0] && t.snapElements.push({
                    item: this,
                    width: n.outerWidth(),
                    height: n.outerHeight(),
                    top: r.top,
                    left: r.left
                })
            })
        },
        drag: function (t, n) {
            var r, i, s, o, u, a, f, l, c, h, p = e(this).data("ui-draggable"),
                d = p.options,
                v = d.snapTolerance,
                m = n.offset.left,
                g = m + p.helperProportions.width,
                y = n.offset.top,
                b = y + p.helperProportions.height;
            for (c = p.snapElements.length - 1; c >= 0; c--) u = p.snapElements[c].left, a = u + p.snapElements[c].width, f = p.snapElements[c].top, l = f + p.snapElements[c].height, m > u - v && a + v > m && y > f - v && l + v > y || m > u - v && a + v > m && b > f - v && l + v > b || g > u - v && a + v > g && y > f - v && l + v > y || g > u - v && a + v > g && b > f - v && l + v > b ? ("inner" !== d.snapMode && (r = Math.abs(f - b) <= v, i = Math.abs(l - y) <= v, s = Math.abs(u - g) <= v, o = Math.abs(a - m) <= v, r && (n.position.top = p._convertPositionTo("relative", {
                top: f - p.helperProportions.height,
                left: 0
            }).top - p.margins.top), i && (n.position.top = p._convertPositionTo("relative", {
                top: l,
                left: 0
            }).top - p.margins.top), s && (n.position.left = p._convertPositionTo("relative", {
                top: 0,
                left: u - p.helperProportions.width
            }).left - p.margins.left), o && (n.position.left = p._convertPositionTo("relative", {
                top: 0,
                left: a
            }).left - p.margins.left)), h = r || i || s || o, "outer" !== d.snapMode && (r = Math.abs(f - y) <= v, i = Math.abs(l - b) <= v, s = Math.abs(u - m) <= v, o = Math.abs(a - g) <= v, r && (n.position.top = p._convertPositionTo("relative", {
                top: f,
                left: 0
            }).top - p.margins.top), i && (n.position.top = p._convertPositionTo("relative", {
                top: l - p.helperProportions.height,
                left: 0
            }).top - p.margins.top), s && (n.position.left = p._convertPositionTo("relative", {
                top: 0,
                left: u
            }).left - p.margins.left), o && (n.position.left = p._convertPositionTo("relative", {
                top: 0,
                left: a - p.helperProportions.width
            }).left - p.margins.left)), !p.snapElements[c].snapping && (r || i || s || o || h) && p.options.snap.snap && p.options.snap.snap.call(p.element, t, e.extend(p._uiHash(), {
                snapItem: p.snapElements[c].item
            })), p.snapElements[c].snapping = r || i || s || o || h) : (p.snapElements[c].snapping && p.options.snap.release && p.options.snap.release.call(p.element, t, e.extend(p._uiHash(), {
                snapItem: p.snapElements[c].item
            })), p.snapElements[c].snapping = !1)
        }
    }), e.ui.plugin.add("draggable", "stack", {
        start: function () {
            var t, n = this.data("ui-draggable").options,
                r = e.makeArray(e(n.stack)).sort(function (t, n) {
                    return (parseInt(e(t).css("zIndex"), 10) || 0) - (parseInt(e(n).css("zIndex"), 10) || 0)
                });
            r.length && (t = parseInt(e(r[0]).css("zIndex"), 10) || 0, e(r).each(function (n) {
                e(this).css("zIndex", t + n)
            }), this.css("zIndex", t + r.length))
        }
    }), e.ui.plugin.add("draggable", "zIndex", {
        start: function (t, n) {
            var r = e(n.helper),
                i = e(this).data("ui-draggable").options;
            r.css("zIndex") && (i._zIndex = r.css("zIndex")), r.css("zIndex", i.zIndex)
        },
        stop: function (t, n) {
            var r = e(this).data("ui-draggable").options;
            r._zIndex && e(n.helper).css("zIndex", r._zIndex)
        }
    })
}(jQuery),
function (e) {
    function n(e, t, n) {
        return e > t && t + n > e
    }
    e.widget("ui.droppable", {
        version: "1.10.1",
        widgetEventPrefix: "drop",
        options: {
            accept: "*",
            activeClass: !1,
            addClasses: !0,
            greedy: !1,
            hoverClass: !1,
            scope: "default",
            tolerance: "intersect",
            activate: null,
            deactivate: null,
            drop: null,
            out: null,
            over: null
        },
        _create: function () {
            var t = this.options,
                n = t.accept;
            this.isover = !1, this.isout = !0, this.accept = e.isFunction(n) ? n : function (e) {
                return e.is(n)
            }, this.proportions = {
                width: this.element[0].offsetWidth,
                height: this.element[0].offsetHeight
            }, e.ui.ddmanager.droppables[t.scope] = e.ui.ddmanager.droppables[t.scope] || [], e.ui.ddmanager.droppables[t.scope].push(this), t.addClasses && this.element.addClass("ui-droppable")
        },
        _destroy: function () {
            for (var t = 0, n = e.ui.ddmanager.droppables[this.options.scope]; t < n.length; t++) n[t] === this && n.splice(t, 1);
            this.element.removeClass("ui-droppable ui-droppable-disabled")
        },
        _setOption: function (t, n) {
            "accept" === t && (this.accept = e.isFunction(n) ? n : function (e) {
                return e.is(n)
            }), e.Widget.prototype._setOption.apply(this, arguments)
        },
        _activate: function (t) {
            var n = e.ui.ddmanager.current;
            this.options.activeClass && this.element.addClass(this.options.activeClass), n && this._trigger("activate", t, this.ui(n))
        },
        _deactivate: function (t) {
            var n = e.ui.ddmanager.current;
            this.options.activeClass && this.element.removeClass(this.options.activeClass), n && this._trigger("deactivate", t, this.ui(n))
        },
        _over: function (t) {
            var n = e.ui.ddmanager.current;
            n && (n.currentItem || n.element)[0] !== this.element[0] && this.accept.call(this.element[0], n.currentItem || n.element) && (this.options.hoverClass && this.element.addClass(this.options.hoverClass), this._trigger("over", t, this.ui(n)))
        },
        _out: function (t) {
            var n = e.ui.ddmanager.current;
            n && (n.currentItem || n.element)[0] !== this.element[0] && this.accept.call(this.element[0], n.currentItem || n.element) && (this.options.hoverClass && this.element.removeClass(this.options.hoverClass), this._trigger("out", t, this.ui(n)))
        },
        _drop: function (t, n) {
            var r = n || e.ui.ddmanager.current,
                i = !1;
            return r && (r.currentItem || r.element)[0] !== this.element[0] ? (this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function () {
                var t = e.data(this, "ui-droppable");
                return t.options.greedy && !t.options.disabled && t.options.scope === r.options.scope && t.accept.call(t.element[0], r.currentItem || r.element) && e.ui.intersect(r, e.extend(t, {
                    offset: t.element.offset()
                }), t.options.tolerance) ? (i = !0, !1) : void 0
            }), i ? !1 : this.accept.call(this.element[0], r.currentItem || r.element) ? (this.options.activeClass && this.element.removeClass(this.options.activeClass), this.options.hoverClass && this.element.removeClass(this.options.hoverClass), this._trigger("drop", t, this.ui(r)), this.element) : !1) : !1
        },
        ui: function (e) {
            return {
                draggable: e.currentItem || e.element,
                helper: e.helper,
                position: e.position,
                offset: e.positionAbs
            }
        }
    }), e.ui.intersect = function (e, t, r) {
        if (!t.offset) return !1;
        var i, s, o = (e.positionAbs || e.position.absolute).left,
            u = o + e.helperProportions.width,
            a = (e.positionAbs || e.position.absolute).top,
            f = a + e.helperProportions.height,
            l = t.offset.left,
            c = l + t.proportions.width,
            h = t.offset.top,
            p = h + t.proportions.height;
        switch (r) {
        case "fit":
            return o >= l && c >= u && a >= h && p >= f;
        case "intersect":
            return l < o + e.helperProportions.width / 2 && u - e.helperProportions.width / 2 < c && h < a + e.helperProportions.height / 2 && f - e.helperProportions.height / 2 < p;
        case "pointer":
            return i = (e.positionAbs || e.position.absolute).left + (e.clickOffset || e.offset.click).left, s = (e.positionAbs || e.position.absolute).top + (e.clickOffset || e.offset.click).top, n(s, h, t.proportions.height) && n(i, l, t.proportions.width);
        case "touch":
            return (a >= h && p >= a || f >= h && p >= f || h > a && f > p) && (o >= l && c >= o || u >= l && c >= u || l > o && u > c);
        default:
            return !1
        }
    }, e.ui.ddmanager = {
        current: null,
        droppables: {
            "default": []
        },
        prepareOffsets: function (t, n) {
            var r, i, s = e.ui.ddmanager.droppables[t.options.scope] || [],
                o = n ? n.type : null,
                u = (t.currentItem || t.element).find(":data(ui-droppable)").addBack();
            e: for (r = 0; r < s.length; r++)
                if (!(s[r].options.disabled || t && !s[r].accept.call(s[r].element[0], t.currentItem || t.element))) {
                    for (i = 0; i < u.length; i++)
                        if (u[i] === s[r].element[0]) {
                            s[r].proportions.height = 0;
                            continue e
                        }
                    s[r].visible = "none" !== s[r].element.css("display"), s[r].visible && ("mousedown" === o && s[r]._activate.call(s[r], n), s[r].offset = s[r].element.offset(), s[r].proportions = {
                        width: s[r].element[0].offsetWidth,
                        height: s[r].element[0].offsetHeight
                    })
                }
        },
        drop: function (t, n) {
            var r = !1;
            return e.each(e.ui.ddmanager.droppables[t.options.scope] || [], function () {
                this.options && (!this.options.disabled && this.visible && e.ui.intersect(t, this, this.options.tolerance) && (r = this._drop.call(this, n) || r), !this.options.disabled && this.visible && this.accept.call(this.element[0], t.currentItem || t.element) && (this.isout = !0, this.isover = !1, this._deactivate.call(this, n)))
            }), r
        },
        dragStart: function (t, n) {
            t.element.parentsUntil("body").bind("scroll.droppable", function () {
                t.options.refreshPositions || e.ui.ddmanager.prepareOffsets(t, n)
            })
        },
        drag: function (t, n) {
            t.options.refreshPositions && e.ui.ddmanager.prepareOffsets(t, n), e.each(e.ui.ddmanager.droppables[t.options.scope] || [], function () {
                if (!this.options.disabled && !this.greedyChild && this.visible) {
                    var r, i, s, o = e.ui.intersect(t, this, this.options.tolerance),
                        u = !o && this.isover ? "isout" : o && !this.isover ? "isover" : null;
                    u && (this.options.greedy && (i = this.options.scope, s = this.element.parents(":data(ui-droppable)").filter(function () {
                        return e.data(this, "ui-droppable").options.scope === i
                    }), s.length && (r = e.data(s[0], "ui-droppable"), r.greedyChild = "isover" === u)), r && "isover" === u && (r.isover = !1, r.isout = !0, r._out.call(r, n)), this[u] = !0, this["isout" === u ? "isover" : "isout"] = !1, this["isover" === u ? "_over" : "_out"].call(this, n), r && "isout" === u && (r.isout = !1, r.isover = !0, r._over.call(r, n)))
                }
            })
        },
        dragStop: function (t, n) {
            t.element.parentsUntil("body").unbind("scroll.droppable"), t.options.refreshPositions || e.ui.ddmanager.prepareOffsets(t, n)
        }
    }
}(jQuery), jQuery.effects || function (e, t) {
    var n = "ui-effects-";
    e.effects = {
        effect: {}
    },
    function (e, t) {
        function h(e, t, n) {
            var r = u[t.type] || {};
            return null == e ? n || !t.def ? null : t.def : (e = r.floor ? ~~e : parseFloat(e), isNaN(e) ? t.def : r.mod ? (e + r.mod) % r.mod : 0 > e ? 0 : r.max < e ? r.max : e)
        }

        function p(t) {
            var n = s(),
                r = n._rgba = [];
            return t = t.toLowerCase(), c(i, function (e, i) {
                var s, u = i.re.exec(t),
                    a = u && i.parse(u),
                    f = i.space || "rgba";
                return a ? (s = n[f](a), n[o[f].cache] = s[o[f].cache], r = n._rgba = s._rgba, !1) : void 0
            }), r.length ? ("0,0,0,0" === r.join() && e.extend(r, l.transparent), n) : l[t]
        }

        function d(e, t, n) {
            return n = (n + 1) % 1, 1 > 6 * n ? e + 6 * (t - e) * n : 1 > 2 * n ? t : 2 > 3 * n ? e + 6 * (t - e) * (2 / 3 - n) : e
        }
        var l, n = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
            r = /^([\-+])=\s*(\d+\.?\d*)/,
            i = [{
                re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
                parse: function (e) {
                    return [e[1], e[2], e[3], e[4]]
                }
            }, {
                re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
                parse: function (e) {
                    return [2.55 * e[1], 2.55 * e[2], 2.55 * e[3], e[4]]
                }
            }, {
                re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
                parse: function (e) {
                    return [parseInt(e[1], 16), parseInt(e[2], 16), parseInt(e[3], 16)]
                }
            }, {
                re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
                parse: function (e) {
                    return [parseInt(e[1] + e[1], 16), parseInt(e[2] + e[2], 16), parseInt(e[3] + e[3], 16)]
                }
            }, {
                re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
                space: "hsla",
                parse: function (e) {
                    return [e[1], e[2] / 100, e[3] / 100, e[4]]
                }
            }],
            s = e.Color = function (t, n, r, i) {
                return new e.Color.fn.parse(t, n, r, i)
            },
            o = {
                rgba: {
                    props: {
                        red: {
                            idx: 0,
                            type: "byte"
                        },
                        green: {
                            idx: 1,
                            type: "byte"
                        },
                        blue: {
                            idx: 2,
                            type: "byte"
                        }
                    }
                },
                hsla: {
                    props: {
                        hue: {
                            idx: 0,
                            type: "degrees"
                        },
                        saturation: {
                            idx: 1,
                            type: "percent"
                        },
                        lightness: {
                            idx: 2,
                            type: "percent"
                        }
                    }
                }
            },
            u = {
                "byte": {
                    floor: !0,
                    max: 255
                },
                percent: {
                    max: 1
                },
                degrees: {
                    mod: 360,
                    floor: !0
                }
            },
            a = s.support = {},
            f = e("<p>")[0],
            c = e.each;
        f.style.cssText = "background-color:rgba(1,1,1,.5)", a.rgba = f.style.backgroundColor.indexOf("rgba") > -1, c(o, function (e, t) {
            t.cache = "_" + e, t.props.alpha = {
                idx: 3,
                type: "percent",
                def: 1
            }
        }), s.fn = e.extend(s.prototype, {
            parse: function (n, r, i, u) {
                if (n === t) return this._rgba = [null, null, null, null], this;
                (n.jquery || n.nodeType) && (n = e(n).css(r), r = t);
                var a = this,
                    f = e.type(n),
                    d = this._rgba = [];
                return r !== t && (n = [n, r, i, u], f = "array"), "string" === f ? this.parse(p(n) || l._default) : "array" === f ? (c(o.rgba.props, function (e, t) {
                    d[t.idx] = h(n[t.idx], t)
                }), this) : "object" === f ? (n instanceof s ? c(o, function (e, t) {
                    n[t.cache] && (a[t.cache] = n[t.cache].slice())
                }) : c(o, function (t, r) {
                    var i = r.cache;
                    c(r.props, function (e, t) {
                        if (!a[i] && r.to) {
                            if ("alpha" === e || null == n[e]) return;
                            a[i] = r.to(a._rgba)
                        }
                        a[i][t.idx] = h(n[e], t, !0)
                    }), a[i] && e.inArray(null, a[i].slice(0, 3)) < 0 && (a[i][3] = 1, r.from && (a._rgba = r.from(a[i])))
                }), this) : void 0
            },
            is: function (e) {
                var t = s(e),
                    n = !0,
                    r = this;
                return c(o, function (e, i) {
                    var s, o = t[i.cache];
                    return o && (s = r[i.cache] || i.to && i.to(r._rgba) || [], c(i.props, function (e, t) {
                        return null != o[t.idx] ? n = o[t.idx] === s[t.idx] : void 0
                    })), n
                }), n
            },
            _space: function () {
                var e = [],
                    t = this;
                return c(o, function (n, r) {
                    t[r.cache] && e.push(n)
                }), e.pop()
            },
            transition: function (e, t) {
                var n = s(e),
                    r = n._space(),
                    i = o[r],
                    a = 0 === this.alpha() ? s("transparent") : this,
                    f = a[i.cache] || i.to(a._rgba),
                    l = f.slice();
                return n = n[i.cache], c(i.props, function (e, r) {
                    var i = r.idx,
                        s = f[i],
                        o = n[i],
                        a = u[r.type] || {};
                    null !== o && (null === s ? l[i] = o : (a.mod && (o - s > a.mod / 2 ? s += a.mod : s - o > a.mod / 2 && (s -= a.mod)), l[i] = h((o - s) * t + s, r)))
                }), this[r](l)
            },
            blend: function (t) {
                if (1 === this._rgba[3]) return this;
                var n = this._rgba.slice(),
                    r = n.pop(),
                    i = s(t)._rgba;
                return s(e.map(n, function (e, t) {
                    return (1 - r) * i[t] + r * e
                }))
            },
            toRgbaString: function () {
                var t = "rgba(",
                    n = e.map(this._rgba, function (e, t) {
                        return null == e ? t > 2 ? 1 : 0 : e
                    });
                return 1 === n[3] && (n.pop(), t = "rgb("), t + n.join() + ")"
            },
            toHslaString: function () {
                var t = "hsla(",
                    n = e.map(this.hsla(), function (e, t) {
                        return null == e && (e = t > 2 ? 1 : 0), t && 3 > t && (e = Math.round(100 * e) + "%"), e
                    });
                return 1 === n[3] && (n.pop(), t = "hsl("), t + n.join() + ")"
            },
            toHexString: function (t) {
                var n = this._rgba.slice(),
                    r = n.pop();
                return t && n.push(~~(255 * r)), "#" + e.map(n, function (e) {
                    return e = (e || 0).toString(16), 1 === e.length ? "0" + e : e
                }).join("")
            },
            toString: function () {
                return 0 === this._rgba[3] ? "transparent" : this.toRgbaString()
            }
        }), s.fn.parse.prototype = s.fn, o.hsla.to = function (e) {
            if (null == e[0] || null == e[1] || null == e[2]) return [null, null, null, e[3]];
            var l, c, t = e[0] / 255,
                n = e[1] / 255,
                r = e[2] / 255,
                i = e[3],
                s = Math.max(t, n, r),
                o = Math.min(t, n, r),
                u = s - o,
                a = s + o,
                f = .5 * a;
            return l = o === s ? 0 : t === s ? 60 * (n - r) / u + 360 : n === s ? 60 * (r - t) / u + 120 : 60 * (t - n) / u + 240, c = 0 === u ? 0 : .5 >= f ? u / a : u / (2 - a), [Math.round(l) % 360, c, f, null == i ? 1 : i]
        }, o.hsla.from = function (e) {
            if (null == e[0] || null == e[1] || null == e[2]) return [null, null, null, e[3]];
            var t = e[0] / 360,
                n = e[1],
                r = e[2],
                i = e[3],
                s = .5 >= r ? r * (1 + n) : r + n - r * n,
                o = 2 * r - s;
            return [Math.round(255 * d(o, s, t + 1 / 3)), Math.round(255 * d(o, s, t)), Math.round(255 * d(o, s, t - 1 / 3)), i]
        }, c(o, function (n, i) {
            var o = i.props,
                u = i.cache,
                a = i.to,
                f = i.from;
            s.fn[n] = function (n) {
                if (a && !this[u] && (this[u] = a(this._rgba)), n === t) return this[u].slice();
                var r, i = e.type(n),
                    l = "array" === i || "object" === i ? n : arguments,
                    p = this[u].slice();
                return c(o, function (e, t) {
                    var n = l["object" === i ? e : t.idx];
                    null == n && (n = p[t.idx]), p[t.idx] = h(n, t)
                }), f ? (r = s(f(p)), r[u] = p, r) : s(p)
            }, c(o, function (t, i) {
                s.fn[t] || (s.fn[t] = function (s) {
                    var l, o = e.type(s),
                        u = "alpha" === t ? this._hsla ? "hsla" : "rgba" : n,
                        a = this[u](),
                        f = a[i.idx];
                    return "undefined" === o ? f : ("function" === o && (s = s.call(this, f), o = e.type(s)), null == s && i.empty ? this : ("string" === o && (l = r.exec(s), l && (s = f + parseFloat(l[2]) * ("+" === l[1] ? 1 : -1))), a[i.idx] = s, this[u](a)))
                })
            })
        }), s.hook = function (t) {
            var n = t.split(" ");
            c(n, function (t, n) {
                e.cssHooks[n] = {
                    set: function (t, r) {
                        var i, o, u = "";
                        if ("transparent" !== r && ("string" !== e.type(r) || (i = p(r)))) {
                            if (r = s(i || r), !a.rgba && 1 !== r._rgba[3]) {
                                for (o = "backgroundColor" === n ? t.parentNode : t;
                                    ("" === u || "transparent" === u) && o && o.style;) try {
                                    u = e.css(o, "backgroundColor"), o = o.parentNode
                                } catch (f) {}
                                r = r.blend(u && "transparent" !== u ? u : "_default")
                            }
                            r = r.toRgbaString()
                        }
                        try {
                            t.style[n] = r
                        } catch (f) {}
                    }
                }, e.fx.step[n] = function (t) {
                    t.colorInit || (t.start = s(t.elem, n), t.end = s(t.end), t.colorInit = !0), e.cssHooks[n].set(t.elem, t.start.transition(t.end, t.pos))
                }
            })
        }, s.hook(n), e.cssHooks.borderColor = {
            expand: function (e) {
                var t = {};
                return c(["Top", "Right", "Bottom", "Left"], function (n, r) {
                    t["border" + r + "Color"] = e
                }), t
            }
        }, l = e.Color.names = {
            aqua: "#00ffff",
            black: "#000000",
            blue: "#0000ff",
            fuchsia: "#ff00ff",
            gray: "#808080",
            green: "#008000",
            lime: "#00ff00",
            maroon: "#800000",
            navy: "#000080",
            olive: "#808000",
            purple: "#800080",
            red: "#ff0000",
            silver: "#c0c0c0",
            teal: "#008080",
            white: "#ffffff",
            yellow: "#ffff00",
            transparent: [null, null, null, 0],
            _default: "#ffffff"
        }
    }(jQuery),
    function () {
        function i(t) {
            var n, r, i = t.ownerDocument.defaultView ? t.ownerDocument.defaultView.getComputedStyle(t, null) : t.currentStyle,
                s = {};
            if (i && i.length && i[0] && i[i[0]])
                for (r = i.length; r--;) n = i[r], "string" == typeof i[n] && (s[e.camelCase(n)] = i[n]);
            else
                for (n in i) "string" == typeof i[n] && (s[n] = i[n]);
            return s
        }

        function s(t, n) {
            var s, o, i = {};
            for (s in n) o = n[s], t[s] !== o && !r[s] && (e.fx.step[s] || !isNaN(parseFloat(o))) && (i[s] = o);
            return i
        }
        var n = ["add", "remove", "toggle"],
            r = {
                border: 1,
                borderBottom: 1,
                borderColor: 1,
                borderLeft: 1,
                borderRight: 1,
                borderTop: 1,
                borderWidth: 1,
                margin: 1,
                padding: 1
            };
        e.each(["borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle"], function (t, n) {
            e.fx.step[n] = function (e) {
                ("none" !== e.end && !e.setAttr || 1 === e.pos && !e.setAttr) && (jQuery.style(e.elem, n, e.end), e.setAttr = !0)
            }
        }), e.fn.addBack || (e.fn.addBack = function (e) {
            return this.add(null == e ? this.prevObject : this.prevObject.filter(e))
        }), e.effects.animateClass = function (t, r, o, u) {
            var a = e.speed(r, o, u);
            return this.queue(function () {
                var u, r = e(this),
                    o = r.attr("class") || "",
                    f = a.children ? r.find("*").addBack() : r;
                f = f.map(function () {
                    var t = e(this);
                    return {
                        el: t,
                        start: i(this)
                    }
                }), u = function () {
                    e.each(n, function (e, n) {
                        t[n] && r[n + "Class"](t[n])
                    })
                }, u(), f = f.map(function () {
                    return this.end = i(this.el[0]), this.diff = s(this.start, this.end), this
                }), r.attr("class", o), f = f.map(function () {
                    var t = this,
                        n = e.Deferred(),
                        r = e.extend({}, a, {
                            queue: !1,
                            complete: function () {
                                n.resolve(t)
                            }
                        });
                    return this.el.animate(this.diff, r), n.promise()
                }), e.when.apply(e, f.get()).done(function () {
                    u(), e.each(arguments, function () {
                        var t = this.el;
                        e.each(this.diff, function (e) {
                            t.css(e, "")
                        })
                    }), a.complete.call(r[0])
                })
            })
        }, e.fn.extend({
            _addClass: e.fn.addClass,
            addClass: function (t, n, r, i) {
                return n ? e.effects.animateClass.call(this, {
                    add: t
                }, n, r, i) : this._addClass(t)
            },
            _removeClass: e.fn.removeClass,
            removeClass: function (t, n, r, i) {
                return arguments.length > 1 ? e.effects.animateClass.call(this, {
                    remove: t
                }, n, r, i) : this._removeClass.apply(this, arguments)
            },
            _toggleClass: e.fn.toggleClass,
            toggleClass: function (n, r, i, s, o) {
                return "boolean" == typeof r || r === t ? i ? e.effects.animateClass.call(this, r ? {
                    add: n
                } : {
                    remove: n
                }, i, s, o) : this._toggleClass(n, r) : e.effects.animateClass.call(this, {
                    toggle: n
                }, r, i, s)
            },
            switchClass: function (t, n, r, i, s) {
                return e.effects.animateClass.call(this, {
                    add: n,
                    remove: t
                }, r, i, s)
            }
        })
    }(),
    function () {
        function r(t, n, r, i) {
            return e.isPlainObject(t) && (n = t, t = t.effect), t = {
                effect: t
            }, null == n && (n = {}), e.isFunction(n) && (i = n, r = null, n = {}), ("number" == typeof n || e.fx.speeds[n]) && (i = r, r = n, n = {}), e.isFunction(r) && (i = r, r = null), n && e.extend(t, n), r = r || n.duration, t.duration = e.fx.off ? 0 : "number" == typeof r ? r : r in e.fx.speeds ? e.fx.speeds[r] : e.fx.speeds._default, t.complete = i || n.complete, t
        }

        function i(t) {
            return !t || "number" == typeof t || e.fx.speeds[t] ? !0 : "string" == typeof t && !e.effects.effect[t]
        }
        e.extend(e.effects, {
            version: "1.10.1",
            save: function (e, t) {
                for (var r = 0; r < t.length; r++) null !== t[r] && e.data(n + t[r], e[0].style[t[r]])
            },
            restore: function (e, r) {
                var i, s;
                for (s = 0; s < r.length; s++) null !== r[s] && (i = e.data(n + r[s]), i === t && (i = ""), e.css(r[s], i))
            },
            setMode: function (e, t) {
                return "toggle" === t && (t = e.is(":hidden") ? "show" : "hide"), t
            },
            getBaseline: function (e, t) {
                var n, r;
                switch (e[0]) {
                case "top":
                    n = 0;
                    break;
                case "middle":
                    n = .5;
                    break;
                case "bottom":
                    n = 1;
                    break;
                default:
                    n = e[0] / t.height
                }
                switch (e[1]) {
                case "left":
                    r = 0;
                    break;
                case "center":
                    r = .5;
                    break;
                case "right":
                    r = 1;
                    break;
                default:
                    r = e[1] / t.width
                }
                return {
                    x: r,
                    y: n
                }
            },
            createWrapper: function (t) {
                if (t.parent().is(".ui-effects-wrapper")) return t.parent();
                var n = {
                        width: t.outerWidth(!0),
                        height: t.outerHeight(!0),
                        "float": t.css("float")
                    },
                    r = e("<div></div>").addClass("ui-effects-wrapper").css({
                        fontSize: "100%",
                        background: "transparent",
                        border: "none",
                        margin: 0,
                        padding: 0
                    }),
                    i = {
                        width: t.width(),
                        height: t.height()
                    },
                    s = document.activeElement;
                try {
                    s.id
                } catch (o) {
                    s = document.body
                }
                return t.wrap(r), (t[0] === s || e.contains(t[0], s)) && e(s).focus(), r = t.parent(), "static" === t.css("position") ? (r.css({
                    position: "relative"
                }), t.css({
                    position: "relative"
                })) : (e.extend(n, {
                    position: t.css("position"),
                    zIndex: t.css("z-index")
                }), e.each(["top", "left", "bottom", "right"], function (e, r) {
                    n[r] = t.css(r), isNaN(parseInt(n[r], 10)) && (n[r] = "auto")
                }), t.css({
                    position: "relative",
                    top: 0,
                    left: 0,
                    right: "auto",
                    bottom: "auto"
                })), t.css(i), r.css(n).show()
            },
            removeWrapper: function (t) {
                var n = document.activeElement;
                return t.parent().is(".ui-effects-wrapper") && (t.parent().replaceWith(t), (t[0] === n || e.contains(t[0], n)) && e(n).focus()), t
            },
            setTransition: function (t, n, r, i) {
                return i = i || {}, e.each(n, function (e, n) {
                    var s = t.cssUnit(n);
                    s[0] > 0 && (i[n] = s[0] * r + s[1])
                }), i
            }
        }), e.fn.extend({
            effect: function () {
                function o(n) {
                    function u() {
                        e.isFunction(i) && i.call(r[0]), e.isFunction(n) && n()
                    }
                    var r = e(this),
                        i = t.complete,
                        o = t.mode;
                    (r.is(":hidden") ? "hide" === o : "show" === o) ? u() : s.call(r[0], t, u)
                }
                var t = r.apply(this, arguments),
                    n = t.mode,
                    i = t.queue,
                    s = e.effects.effect[t.effect];
                return e.fx.off || !s ? n ? this[n](t.duration, t.complete) : this.each(function () {
                    t.complete && t.complete.call(this)
                }) : i === !1 ? this.each(o) : this.queue(i || "fx", o)
            },
            _show: e.fn.show,
            show: function (e) {
                if (i(e)) return this._show.apply(this, arguments);
                var t = r.apply(this, arguments);
                return t.mode = "show", this.effect.call(this, t)
            },
            _hide: e.fn.hide,
            hide: function (e) {
                if (i(e)) return this._hide.apply(this, arguments);
                var t = r.apply(this, arguments);
                return t.mode = "hide", this.effect.call(this, t)
            },
            __toggle: e.fn.toggle,
            toggle: function (t) {
                if (i(t) || "boolean" == typeof t || e.isFunction(t)) return this.__toggle.apply(this, arguments);
                var n = r.apply(this, arguments);
                return n.mode = "toggle", this.effect.call(this, n)
            },
            cssUnit: function (t) {
                var n = this.css(t),
                    r = [];
                return e.each(["em", "px", "%", "pt"], function (e, t) {
                    n.indexOf(t) > 0 && (r = [parseFloat(n), t])
                }), r
            }
        })
    }(),
    function () {
        var t = {};
        e.each(["Quad", "Cubic", "Quart", "Quint", "Expo"], function (e, n) {
            t[n] = function (t) {
                return Math.pow(t, e + 2)
            }
        }), e.extend(t, {
            Sine: function (e) {
                return 1 - Math.cos(e * Math.PI / 2)
            },
            Circ: function (e) {
                return 1 - Math.sqrt(1 - e * e)
            },
            Elastic: function (e) {
                return 0 === e || 1 === e ? e : -Math.pow(2, 8 * (e - 1)) * Math.sin((80 * (e - 1) - 7.5) * Math.PI / 15)
            },
            Back: function (e) {
                return e * e * (3 * e - 2)
            },
            Bounce: function (e) {
                for (var t, n = 4; e < ((t = Math.pow(2, --n)) - 1) / 11;);
                return 1 / Math.pow(4, 3 - n) - 7.5625 * Math.pow((3 * t - 2) / 22 - e, 2)
            }
        }), e.each(t, function (t, n) {
            e.easing["easeIn" + t] = n, e.easing["easeOut" + t] = function (e) {
                return 1 - n(1 - e)
            }, e.easing["easeInOut" + t] = function (e) {
                return .5 > e ? n(2 * e) / 2 : 1 - n(-2 * e + 2) / 2
            }
        })
    }()
}(jQuery),
function (e) {
    var n = /up|down|vertical/,
        r = /up|left|vertical|horizontal/;
    e.effects.effect.blind = function (t, i) {
        var v, m, g, s = e(this),
            o = ["position", "top", "bottom", "left", "right", "height", "width"],
            u = e.effects.setMode(s, t.mode || "hide"),
            a = t.direction || "up",
            f = n.test(a),
            l = f ? "height" : "width",
            c = f ? "top" : "left",
            h = r.test(a),
            p = {},
            d = "show" === u;
        s.parent().is(".ui-effects-wrapper") ? e.effects.save(s.parent(), o) : e.effects.save(s, o), s.show(), v = e.effects.createWrapper(s).css({
            overflow: "hidden"
        }), m = v[l](), g = parseFloat(v.css(c)) || 0, p[l] = d ? m : 0, h || (s.css(f ? "bottom" : "right", 0).css(f ? "top" : "left", "auto").css({
            position: "absolute"
        }), p[c] = d ? g : m + g), d && (v.css(l, 0), h || v.css(c, g + m)), v.animate(p, {
            duration: t.duration,
            easing: t.easing,
            queue: !1,
            complete: function () {
                "hide" === u && s.hide(), e.effects.restore(s, o), e.effects.removeWrapper(s), i()
            }
        })
    }
}(jQuery),
function (e) {
    e.effects.effect.bounce = function (t, n) {
        var m, g, y, r = e(this),
            i = ["position", "top", "bottom", "left", "right", "height", "width"],
            s = e.effects.setMode(r, t.mode || "effect"),
            o = "hide" === s,
            u = "show" === s,
            a = t.direction || "up",
            f = t.distance,
            l = t.times || 5,
            c = 2 * l + (u || o ? 1 : 0),
            h = t.duration / c,
            p = t.easing,
            d = "up" === a || "down" === a ? "top" : "left",
            v = "up" === a || "left" === a,
            b = r.queue(),
            w = b.length;
        for ((u || o) && i.push("opacity"), e.effects.save(r, i), r.show(), e.effects.createWrapper(r), f || (f = r["top" === d ? "outerHeight" : "outerWidth"]() / 3), u && (y = {
            opacity: 1
        }, y[d] = 0, r.css("opacity", 0).css(d, v ? 2 * -f : 2 * f).animate(y, h, p)), o && (f /= Math.pow(2, l - 1)), y = {}, y[d] = 0, m = 0; l > m; m++) g = {}, g[d] = (v ? "-=" : "+=") + f, r.animate(g, h, p).animate(y, h, p), f = o ? 2 * f : f / 2;
        o && (g = {
            opacity: 0
        }, g[d] = (v ? "-=" : "+=") + f, r.animate(g, h, p)), r.queue(function () {
            o && r.hide(), e.effects.restore(r, i), e.effects.removeWrapper(r), n()
        }), w > 1 && b.splice.apply(b, [1, 0].concat(b.splice(w, c + 1))), r.dequeue()
    }
}(jQuery),
function (e) {
    e.effects.effect.clip = function (t, n) {
        var h, p, d, r = e(this),
            i = ["position", "top", "bottom", "left", "right", "height", "width"],
            s = e.effects.setMode(r, t.mode || "hide"),
            o = "show" === s,
            u = t.direction || "vertical",
            a = "vertical" === u,
            f = a ? "height" : "width",
            l = a ? "top" : "left",
            c = {};
        e.effects.save(r, i), r.show(), h = e.effects.createWrapper(r).css({
            overflow: "hidden"
        }), p = "IMG" === r[0].tagName ? h : r, d = p[f](), o && (p.css(f, 0), p.css(l, d / 2)), c[f] = o ? d : 0, c[l] = o ? 0 : d / 2, p.animate(c, {
            queue: !1,
            duration: t.duration,
            easing: t.easing,
            complete: function () {
                o || r.hide(), e.effects.restore(r, i), e.effects.removeWrapper(r), n()
            }
        })
    }
}(jQuery),
function (e) {
    e.effects.effect.drop = function (t, n) {
        var c, r = e(this),
            i = ["position", "top", "bottom", "left", "right", "opacity", "height", "width"],
            s = e.effects.setMode(r, t.mode || "hide"),
            o = "show" === s,
            u = t.direction || "left",
            a = "up" === u || "down" === u ? "top" : "left",
            f = "up" === u || "left" === u ? "pos" : "neg",
            l = {
                opacity: o ? 1 : 0
            };
        e.effects.save(r, i), r.show(), e.effects.createWrapper(r), c = t.distance || r["top" === a ? "outerHeight" : "outerWidth"](!0) / 2, o && r.css("opacity", 0).css(a, "pos" === f ? -c : c), l[a] = (o ? "pos" === f ? "+=" : "-=" : "pos" === f ? "-=" : "+=") + c, r.animate(l, {
            queue: !1,
            duration: t.duration,
            easing: t.easing,
            complete: function () {
                "hide" === s && r.hide(), e.effects.restore(r, i), e.effects.removeWrapper(r), n()
            }
        })
    }
}(jQuery),
function (e) {
    e.effects.effect.explode = function (t, n) {
        function y() {
            c.push(this), c.length === r * i && b()
        }

        function b() {
            s.css({
                visibility: "visible"
            }), e(c).remove(), u || s.hide(), n()
        }
        var h, p, d, v, m, g, r = t.pieces ? Math.round(Math.sqrt(t.pieces)) : 3,
            i = r,
            s = e(this),
            o = e.effects.setMode(s, t.mode || "hide"),
            u = "show" === o,
            a = s.show().css("visibility", "hidden").offset(),
            f = Math.ceil(s.outerWidth() / i),
            l = Math.ceil(s.outerHeight() / r),
            c = [];
        for (h = 0; r > h; h++)
            for (v = a.top + h * l, g = h - (r - 1) / 2, p = 0; i > p; p++) d = a.left + p * f, m = p - (i - 1) / 2, s.clone().appendTo("body").wrap("<div></div>").css({
                position: "absolute",
                visibility: "visible",
                left: -p * f,
                top: -h * l
            }).parent().addClass("ui-effects-explode").css({
                position: "absolute",
                overflow: "hidden",
                width: f,
                height: l,
                left: d + (u ? m * f : 0),
                top: v + (u ? g * l : 0),
                opacity: u ? 0 : 1
            }).animate({
                left: d + (u ? 0 : m * f),
                top: v + (u ? 0 : g * l),
                opacity: u ? 1 : 0
            }, t.duration || 500, t.easing, y)
    }
}(jQuery),
function (e) {
    e.effects.effect.fade = function (t, n) {
        var r = e(this),
            i = e.effects.setMode(r, t.mode || "toggle");
        r.animate({
            opacity: i
        }, {
            queue: !1,
            duration: t.duration,
            easing: t.easing,
            complete: n
        })
    }
}(jQuery),
function (e) {
    e.effects.effect.fold = function (t, n) {
        var d, v, r = e(this),
            i = ["position", "top", "bottom", "left", "right", "height", "width"],
            s = e.effects.setMode(r, t.mode || "hide"),
            o = "show" === s,
            u = "hide" === s,
            a = t.size || 15,
            f = /([0-9]+)%/.exec(a),
            l = !!t.horizFirst,
            c = o !== l,
            h = c ? ["width", "height"] : ["height", "width"],
            p = t.duration / 2,
            m = {},
            g = {};
        e.effects.save(r, i), r.show(), d = e.effects.createWrapper(r).css({
            overflow: "hidden"
        }), v = c ? [d.width(), d.height()] : [d.height(), d.width()], f && (a = parseInt(f[1], 10) / 100 * v[u ? 0 : 1]), o && d.css(l ? {
            height: 0,
            width: a
        } : {
            height: a,
            width: 0
        }), m[h[0]] = o ? v[0] : a, g[h[1]] = o ? v[1] : 0, d.animate(m, p, t.easing).animate(g, p, t.easing, function () {
            u && r.hide(), e.effects.restore(r, i), e.effects.removeWrapper(r), n()
        })
    }
}(jQuery),
function (e) {
    e.effects.effect.highlight = function (t, n) {
        var r = e(this),
            i = ["backgroundImage", "backgroundColor", "opacity"],
            s = e.effects.setMode(r, t.mode || "show"),
            o = {
                backgroundColor: r.css("backgroundColor")
            };
        "hide" === s && (o.opacity = 0), e.effects.save(r, i), r.show().css({
            backgroundImage: "none",
            backgroundColor: t.color || "#ffff99"
        }).animate(o, {
            queue: !1,
            duration: t.duration,
            easing: t.easing,
            complete: function () {
                "hide" === s && r.hide(), e.effects.restore(r, i), n()
            }
        })
    }
}(jQuery),
function (e) {
    e.effects.effect.pulsate = function (t, n) {
        var p, r = e(this),
            i = e.effects.setMode(r, t.mode || "show"),
            s = "show" === i,
            o = "hide" === i,
            u = s || "hide" === i,
            a = 2 * (t.times || 5) + (u ? 1 : 0),
            f = t.duration / a,
            l = 0,
            c = r.queue(),
            h = c.length;
        for ((s || !r.is(":visible")) && (r.css("opacity", 0).show(), l = 1), p = 1; a > p; p++) r.animate({
            opacity: l
        }, f, t.easing), l = 1 - l;
        r.animate({
            opacity: l
        }, f, t.easing), r.queue(function () {
            o && r.hide(), n()
        }), h > 1 && c.splice.apply(c, [1, 0].concat(c.splice(h, a + 1))), r.dequeue()
    }
}(jQuery),
function (e) {
    e.effects.effect.puff = function (t, n) {
        var r = e(this),
            i = e.effects.setMode(r, t.mode || "hide"),
            s = "hide" === i,
            o = parseInt(t.percent, 10) || 150,
            u = o / 100,
            a = {
                height: r.height(),
                width: r.width(),
                outerHeight: r.outerHeight(),
                outerWidth: r.outerWidth()
            };
        e.extend(t, {
            effect: "scale",
            queue: !1,
            fade: !0,
            mode: i,
            complete: n,
            percent: s ? o : 100,
            from: s ? a : {
                height: a.height * u,
                width: a.width * u,
                outerHeight: a.outerHeight * u,
                outerWidth: a.outerWidth * u
            }
        }), r.effect(t)
    }, e.effects.effect.scale = function (t, n) {
        var r = e(this),
            i = e.extend(!0, {}, t),
            s = e.effects.setMode(r, t.mode || "effect"),
            o = parseInt(t.percent, 10) || (0 === parseInt(t.percent, 10) ? 0 : "hide" === s ? 0 : 100),
            u = t.direction || "both",
            a = t.origin,
            f = {
                height: r.height(),
                width: r.width(),
                outerHeight: r.outerHeight(),
                outerWidth: r.outerWidth()
            },
            l = {
                y: "horizontal" !== u ? o / 100 : 1,
                x: "vertical" !== u ? o / 100 : 1
            };
        i.effect = "size", i.queue = !1, i.complete = n, "effect" !== s && (i.origin = a || ["middle", "center"], i.restore = !0), i.from = t.from || ("show" === s ? {
            height: 0,
            width: 0,
            outerHeight: 0,
            outerWidth: 0
        } : f), i.to = {
            height: f.height * l.y,
            width: f.width * l.x,
            outerHeight: f.outerHeight * l.y,
            outerWidth: f.outerWidth * l.x
        }, i.fade && ("show" === s && (i.from.opacity = 0, i.to.opacity = 1), "hide" === s && (i.from.opacity = 1, i.to.opacity = 0)), r.effect(i)
    }, e.effects.effect.size = function (t, n) {
        var r, i, s, o = e(this),
            u = ["position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity"],
            a = ["position", "top", "bottom", "left", "right", "overflow", "opacity"],
            f = ["width", "height", "overflow"],
            l = ["fontSize"],
            c = ["borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom"],
            h = ["borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight"],
            p = e.effects.setMode(o, t.mode || "effect"),
            d = t.restore || "effect" !== p,
            v = t.scale || "both",
            m = t.origin || ["middle", "center"],
            g = o.css("position"),
            y = d ? u : a,
            b = {
                height: 0,
                width: 0,
                outerHeight: 0,
                outerWidth: 0
            };
        "show" === p && o.show(), r = {
            height: o.height(),
            width: o.width(),
            outerHeight: o.outerHeight(),
            outerWidth: o.outerWidth()
        }, "toggle" === t.mode && "show" === p ? (o.from = t.to || b, o.to = t.from || r) : (o.from = t.from || ("show" === p ? b : r), o.to = t.to || ("hide" === p ? b : r)), s = {
            from: {
                y: o.from.height / r.height,
                x: o.from.width / r.width
            },
            to: {
                y: o.to.height / r.height,
                x: o.to.width / r.width
            }
        }, ("box" === v || "both" === v) && (s.from.y !== s.to.y && (y = y.concat(c), o.from = e.effects.setTransition(o, c, s.from.y, o.from), o.to = e.effects.setTransition(o, c, s.to.y, o.to)), s.from.x !== s.to.x && (y = y.concat(h), o.from = e.effects.setTransition(o, h, s.from.x, o.from), o.to = e.effects.setTransition(o, h, s.to.x, o.to))), ("content" === v || "both" === v) && s.from.y !== s.to.y && (y = y.concat(l).concat(f), o.from = e.effects.setTransition(o, l, s.from.y, o.from), o.to = e.effects.setTransition(o, l, s.to.y, o.to)), e.effects.save(o, y), o.show(), e.effects.createWrapper(o), o.css("overflow", "hidden").css(o.from), m && (i = e.effects.getBaseline(m, r), o.from.top = (r.outerHeight - o.outerHeight()) * i.y, o.from.left = (r.outerWidth - o.outerWidth()) * i.x, o.to.top = (r.outerHeight - o.to.outerHeight) * i.y, o.to.left = (r.outerWidth - o.to.outerWidth) * i.x), o.css(o.from), ("content" === v || "both" === v) && (c = c.concat(["marginTop", "marginBottom"]).concat(l), h = h.concat(["marginLeft", "marginRight"]), f = u.concat(c).concat(h), o.find("*[width]").each(function () {
            var n = e(this),
                r = {
                    height: n.height(),
                    width: n.width(),
                    outerHeight: n.outerHeight(),
                    outerWidth: n.outerWidth()
                };
            d && e.effects.save(n, f), n.from = {
                height: r.height * s.from.y,
                width: r.width * s.from.x,
                outerHeight: r.outerHeight * s.from.y,
                outerWidth: r.outerWidth * s.from.x
            }, n.to = {
                height: r.height * s.to.y,
                width: r.width * s.to.x,
                outerHeight: r.height * s.to.y,
                outerWidth: r.width * s.to.x
            }, s.from.y !== s.to.y && (n.from = e.effects.setTransition(n, c, s.from.y, n.from), n.to = e.effects.setTransition(n, c, s.to.y, n.to)), s.from.x !== s.to.x && (n.from = e.effects.setTransition(n, h, s.from.x, n.from), n.to = e.effects.setTransition(n, h, s.to.x, n.to)), n.css(n.from), n.animate(n.to, t.duration, t.easing, function () {
                d && e.effects.restore(n, f)
            })
        })), o.animate(o.to, {
            queue: !1,
            duration: t.duration,
            easing: t.easing,
            complete: function () {
                0 === o.to.opacity && o.css("opacity", o.from.opacity), "hide" === p && o.hide(), e.effects.restore(o, y), d || ("static" === g ? o.css({
                    position: "relative",
                    top: o.to.top,
                    left: o.to.left
                }) : e.each(["top", "left"], function (e, t) {
                    o.css(t, function (t, n) {
                        var r = parseInt(n, 10),
                            i = e ? o.to.left : o.to.top;
                        return "auto" === n ? i + "px" : r + i + "px"
                    })
                })), e.effects.removeWrapper(o), n()
            }
        })
    }
}(jQuery),
function (e) {
    e.effects.effect.shake = function (t, n) {
        var m, r = e(this),
            i = ["position", "top", "bottom", "left", "right", "height", "width"],
            s = e.effects.setMode(r, t.mode || "effect"),
            o = t.direction || "left",
            u = t.distance || 20,
            a = t.times || 3,
            f = 2 * a + 1,
            l = Math.round(t.duration / f),
            c = "up" === o || "down" === o ? "top" : "left",
            h = "up" === o || "left" === o,
            p = {},
            d = {},
            v = {},
            g = r.queue(),
            y = g.length;
        for (e.effects.save(r, i), r.show(), e.effects.createWrapper(r), p[c] = (h ? "-=" : "+=") + u, d[c] = (h ? "+=" : "-=") + 2 * u, v[c] = (h ? "-=" : "+=") + 2 * u, r.animate(p, l, t.easing), m = 1; a > m; m++) r.animate(d, l, t.easing).animate(v, l, t.easing);
        r.animate(d, l, t.easing).animate(p, l / 2, t.easing).queue(function () {
            "hide" === s && r.hide(), e.effects.restore(r, i), e.effects.removeWrapper(r), n()
        }), y > 1 && g.splice.apply(g, [1, 0].concat(g.splice(y, f + 1))), r.dequeue()
    }
}(jQuery),
function (e) {
    e.effects.effect.slide = function (t, n) {
        var l, r = e(this),
            i = ["position", "top", "bottom", "left", "right", "width", "height"],
            s = e.effects.setMode(r, t.mode || "show"),
            o = "show" === s,
            u = t.direction || "left",
            a = "up" === u || "down" === u ? "top" : "left",
            f = "up" === u || "left" === u,
            c = {};
        e.effects.save(r, i), r.show(), l = t.distance || r["top" === a ? "outerHeight" : "outerWidth"](!0), e.effects.createWrapper(r).css({
            overflow: "hidden"
        }), o && r.css(a, f ? isNaN(l) ? "-" + l : -l : l), c[a] = (o ? f ? "+=" : "-=" : f ? "-=" : "+=") + l, r.animate(c, {
            queue: !1,
            duration: t.duration,
            easing: t.easing,
            complete: function () {
                "hide" === s && r.hide(), e.effects.restore(r, i), e.effects.removeWrapper(r), n()
            }
        })
    }
}(jQuery),
function (e) {
    e.effects.effect.transfer = function (t, n) {
        var r = e(this),
            i = e(t.to),
            s = "fixed" === i.css("position"),
            o = e("body"),
            u = s ? o.scrollTop() : 0,
            a = s ? o.scrollLeft() : 0,
            f = i.offset(),
            l = {
                top: f.top - u,
                left: f.left - a,
                height: i.innerHeight(),
                width: i.innerWidth()
            },
            c = r.offset(),
            h = e("<div class='ui-effects-transfer'></div>").appendTo(document.body).addClass(t.className).css({
                top: c.top - u,
                left: c.left - a,
                height: r.innerHeight(),
                width: r.innerWidth(),
                position: s ? "fixed" : "absolute"
            }).animate(l, t.duration, t.easing, function () {
                h.remove(), n()
            })
    }
}(jQuery),
function (e) {
    e.widget("ui.menu", {
        version: "1.10.1",
        defaultElement: "<ul>",
        delay: 300,
        options: {
            icons: {
                submenu: "ui-icon-carat-1-e"
            },
            menus: "ul",
            position: {
                my: "left top",
                at: "right top"
            },
            role: "menu",
            blur: null,
            focus: null,
            select: null
        },
        _create: function () {
            this.activeMenu = this.element, this.mouseHandled = !1, this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons", !!this.element.find(".ui-icon").length).attr({
                role: this.options.role,
                tabIndex: 0
            }).bind("click" + this.eventNamespace, e.proxy(function (e) {
                this.options.disabled && e.preventDefault()
            }, this)), this.options.disabled && this.element.addClass("ui-state-disabled").attr("aria-disabled", "true"), this._on({
                "mousedown .ui-menu-item > a": function (e) {
                    e.preventDefault()
                },
                "click .ui-state-disabled > a": function (e) {
                    e.preventDefault()
                },
                "click .ui-menu-item:has(a)": function (t) {
                    var n = e(t.target).closest(".ui-menu-item");
                    !this.mouseHandled && n.not(".ui-state-disabled").length && (this.mouseHandled = !0, this.select(t), n.has(".ui-menu").length ? this.expand(t) : this.element.is(":focus") || (this.element.trigger("focus", [!0]), this.active && 1 === this.active.parents(".ui-menu").length && clearTimeout(this.timer)))
                },
                "mouseenter .ui-menu-item": function (t) {
                    var n = e(t.currentTarget);
                    n.siblings().children(".ui-state-active").removeClass("ui-state-active"), this.focus(t, n)
                },
                mouseleave: "collapseAll",
                "mouseleave .ui-menu": "collapseAll",
                focus: function (e, t) {
                    var n = this.active || this.element.children(".ui-menu-item").eq(0);
                    t || this.focus(e, n)
                },
                blur: function (t) {
                    this._delay(function () {
                        e.contains(this.element[0], this.document[0].activeElement) || this.collapseAll(t)
                    })
                },
                keydown: "_keydown"
            }), this.refresh(), this._on(this.document, {
                click: function (t) {
                    e(t.target).closest(".ui-menu").length || this.collapseAll(t), this.mouseHandled = !1
                }
            })
        },
        _destroy: function () {
            this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(), this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function () {
                var t = e(this);
                t.data("ui-menu-submenu-carat") && t.remove()
            }), this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")
        },
        _keydown: function (t) {
            function a(e) {
                return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&")
            }
            var n, r, i, s, o, u = !0;
            switch (t.keyCode) {
            case e.ui.keyCode.PAGE_UP:
                this.previousPage(t);
                break;
            case e.ui.keyCode.PAGE_DOWN:
                this.nextPage(t);
                break;
            case e.ui.keyCode.HOME:
                this._move("first", "first", t);
                break;
            case e.ui.keyCode.END:
                this._move("last", "last", t);
                break;
            case e.ui.keyCode.UP:
                this.previous(t);
                break;
            case e.ui.keyCode.DOWN:
                this.next(t);
                break;
            case e.ui.keyCode.LEFT:
                this.collapse(t);
                break;
            case e.ui.keyCode.RIGHT:
                this.active && !this.active.is(".ui-state-disabled") && this.expand(t);
                break;
            case e.ui.keyCode.ENTER:
            case e.ui.keyCode.SPACE:
                this._activate(t);
                break;
            case e.ui.keyCode.ESCAPE:
                this.collapse(t);
                break;
            default:
                u = !1, r = this.previousFilter || "", i = String.fromCharCode(t.keyCode), s = !1, clearTimeout(this.filterTimer), i === r ? s = !0 : i = r + i, o = new RegExp("^" + a(i), "i"), n = this.activeMenu.children(".ui-menu-item").filter(function () {
                    return o.test(e(this).children("a").text())
                }), n = s && -1 !== n.index(this.active.next()) ? this.active.nextAll(".ui-menu-item") : n, n.length || (i = String.fromCharCode(t.keyCode), o = new RegExp("^" + a(i), "i"), n = this.activeMenu.children(".ui-menu-item").filter(function () {
                    return o.test(e(this).children("a").text())
                })), n.length ? (this.focus(t, n), n.length > 1 ? (this.previousFilter = i, this.filterTimer = this._delay(function () {
                    delete this.previousFilter
                }, 1e3)) : delete this.previousFilter) : delete this.previousFilter
            }
            u && t.preventDefault()
        },
        _activate: function (e) {
            this.active.is(".ui-state-disabled") || (this.active.children("a[aria-haspopup='true']").length ? this.expand(e) : this.select(e))
        },
        refresh: function () {
            var t, n = this.options.icons.submenu,
                r = this.element.find(this.options.menus);
            r.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({
                role: this.options.role,
                "aria-hidden": "true",
                "aria-expanded": "false"
            }).each(function () {
                var t = e(this),
                    r = t.prev("a"),
                    i = e("<span>").addClass("ui-menu-icon ui-icon " + n).data("ui-menu-submenu-carat", !0);
                r.attr("aria-haspopup", "true").prepend(i), t.attr("aria-labelledby", r.attr("id"))
            }), t = r.add(this.element), t.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role", "presentation").children("a").uniqueId().addClass("ui-corner-all").attr({
                tabIndex: -1,
                role: this._itemRole()
            }), t.children(":not(.ui-menu-item)").each(function () {
                var t = e(this);
                /[^\-\u2014\u2013\s]/.test(t.text()) || t.addClass("ui-widget-content ui-menu-divider")
            }), t.children(".ui-state-disabled").attr("aria-disabled", "true"), this.active && !e.contains(this.element[0], this.active[0]) && this.blur()
        },
        _itemRole: function () {
            return {
                menu: "menuitem",
                listbox: "option"
            }[this.options.role]
        },
        _setOption: function (e, t) {
            "icons" === e && this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(t.submenu), this._super(e, t)
        },
        focus: function (e, t) {
            var n, r;
            this.blur(e, e && "focus" === e.type), this._scrollIntoView(t), this.active = t.first(), r = this.active.children("a").addClass("ui-state-focus"), this.options.role && this.element.attr("aria-activedescendant", r.attr("id")), this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"), e && "keydown" === e.type ? this._close() : this.timer = this._delay(function () {
                this._close()
            }, this.delay), n = t.children(".ui-menu"), n.length && /^mouse/.test(e.type) && this._startOpening(n), this.activeMenu = t.parent(), this._trigger("focus", e, {
                item: t
            })
        },
        _scrollIntoView: function (t) {
            var n, r, i, s, o, u;
            this._hasScroll() && (n = parseFloat(e.css(this.activeMenu[0], "borderTopWidth")) || 0, r = parseFloat(e.css(this.activeMenu[0], "paddingTop")) || 0, i = t.offset().top - this.activeMenu.offset().top - n - r, s = this.activeMenu.scrollTop(), o = this.activeMenu.height(), u = t.height(), 0 > i ? this.activeMenu.scrollTop(s + i) : i + u > o && this.activeMenu.scrollTop(s + i - o + u))
        },
        blur: function (e, t) {
            t || clearTimeout(this.timer), this.active && (this.active.children("a").removeClass("ui-state-focus"), this.active = null, this._trigger("blur", e, {
                item: this.active
            }))
        },
        _startOpening: function (e) {
            clearTimeout(this.timer), "true" === e.attr("aria-hidden") && (this.timer = this._delay(function () {
                this._close(), this._open(e)
            }, this.delay))
        },
        _open: function (t) {
            var n = e.extend({
                of: this.active
            }, this.options.position);
            clearTimeout(this.timer), this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden", "true"), t.show().removeAttr("aria-hidden").attr("aria-expanded", "true").position(n)
        },
        collapseAll: function (t, n) {
            clearTimeout(this.timer), this.timer = this._delay(function () {
                var r = n ? this.element : e(t && t.target).closest(this.element.find(".ui-menu"));
                r.length || (r = this.element), this._close(r), this.blur(t), this.activeMenu = r
            }, this.delay)
        },
        _close: function (e) {
            e || (e = this.active ? this.active.parent() : this.element), e.find(".ui-menu").hide().attr("aria-hidden", "true").attr("aria-expanded", "false").end().find("a.ui-state-active").removeClass("ui-state-active")
        },
        collapse: function (e) {
            var t = this.active && this.active.parent().closest(".ui-menu-item", this.element);
            t && t.length && (this._close(), this.focus(e, t))
        },
        expand: function (e) {
            var t = this.active && this.active.children(".ui-menu ").children(".ui-menu-item").first();
            t && t.length && (this._open(t.parent()), this._delay(function () {
                this.focus(e, t)
            }))
        },
        next: function (e) {
            this._move("next", "first", e)
        },
        previous: function (e) {
            this._move("prev", "last", e)
        },
        isFirstItem: function () {
            return this.active && !this.active.prevAll(".ui-menu-item").length
        },
        isLastItem: function () {
            return this.active && !this.active.nextAll(".ui-menu-item").length
        },
        _move: function (e, t, n) {
            var r;
            this.active && (r = "first" === e || "last" === e ? this.active["first" === e ? "prevAll" : "nextAll"](".ui-menu-item").eq(-1) : this.active[e + "All"](".ui-menu-item").eq(0)), r && r.length && this.active || (r = this.activeMenu.children(".ui-menu-item")[t]()), this.focus(n, r)
        },
        nextPage: function (t) {
            var n, r, i;
            return this.active ? (this.isLastItem() || (this._hasScroll() ? (r = this.active.offset().top, i = this.element.height(), this.active.nextAll(".ui-menu-item").each(function () {
                return n = e(this), n.offset().top - r - i < 0
            }), this.focus(t, n)) : this.focus(t, this.activeMenu.children(".ui-menu-item")[this.active ? "last" : "first"]())), void 0) : (this.next(t), void 0)
        },
        previousPage: function (t) {
            var n, r, i;
            return this.active ? (this.isFirstItem() || (this._hasScroll() ? (r = this.active.offset().top, i = this.element.height(), this.active.prevAll(".ui-menu-item").each(function () {
                return n = e(this), n.offset().top - r + i > 0
            }), this.focus(t, n)) : this.focus(t, this.activeMenu.children(".ui-menu-item").first())), void 0) : (this.next(t), void 0)
        },
        _hasScroll: function () {
            return this.element.outerHeight() < this.element.prop("scrollHeight")
        },
        select: function (t) {
            this.active = this.active || e(t.target).closest(".ui-menu-item");
            var n = {
                item: this.active
            };
            this.active.has(".ui-menu").length || this.collapseAll(t, !0), this._trigger("select", t, n)
        }
    })
}(jQuery),
function (e, t) {
    e.widget("ui.progressbar", {
        version: "1.10.1",
        options: {
            max: 100,
            value: 0,
            change: null,
            complete: null
        },
        min: 0,
        _create: function () {
            this.oldValue = this.options.value = this._constrainedValue(), this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({
                role: "progressbar",
                "aria-valuemin": this.min
            }), this.valueDiv = e("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element), this._refreshValue()
        },
        _destroy: function () {
            this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"), this.valueDiv.remove()
        },
        value: function (e) {
            return e === t ? this.options.value : (this.options.value = this._constrainedValue(e), this._refreshValue(), void 0)
        },
        _constrainedValue: function (e) {
            return e === t && (e = this.options.value), this.indeterminate = e === !1, "number" != typeof e && (e = 0), this.indeterminate ? !1 : Math.min(this.options.max, Math.max(this.min, e))
        },
        _setOptions: function (e) {
            var t = e.value;
            delete e.value, this._super(e), this.options.value = this._constrainedValue(t), this._refreshValue()
        },
        _setOption: function (e, t) {
            "max" === e && (t = Math.max(this.min, t)), this._super(e, t)
        },
        _percentage: function () {
            return this.indeterminate ? 100 : 100 * (this.options.value - this.min) / (this.options.max - this.min)
        },
        _refreshValue: function () {
            var t = this.options.value,
                n = this._percentage();
            this.valueDiv.toggle(this.indeterminate || t > this.min).toggleClass("ui-corner-right", t === this.options.max).width(n.toFixed(0) + "%"), this.element.toggleClass("ui-progressbar-indeterminate", this.indeterminate), this.indeterminate ? (this.element.removeAttr("aria-valuenow"), this.overlayDiv || (this.overlayDiv = e("<div class='ui-progressbar-overlay'></div>").appendTo(this.valueDiv))) : (this.element.attr({
                "aria-valuemax": this.options.max,
                "aria-valuenow": t
            }), this.overlayDiv && (this.overlayDiv.remove(), this.overlayDiv = null)), this.oldValue !== t && (this.oldValue = t, this._trigger("change")), t === this.options.max && this._trigger("complete")
        }
    })
}(jQuery),
function (e) {
    function n(e) {
        return parseInt(e, 10) || 0
    }

    function r(e) {
        return !isNaN(parseInt(e, 10))
    }
    e.widget("ui.resizable", e.ui.mouse, {
        version: "1.10.1",
        widgetEventPrefix: "resize",
        options: {
            alsoResize: !1,
            animate: !1,
            animateDuration: "slow",
            animateEasing: "swing",
            aspectRatio: !1,
            autoHide: !1,
            containment: !1,
            ghost: !1,
            grid: !1,
            handles: "e,s,se",
            helper: !1,
            maxHeight: null,
            maxWidth: null,
            minHeight: 10,
            minWidth: 10,
            zIndex: 90,
            resize: null,
            start: null,
            stop: null
        },
        _create: function () {
            var t, n, r, i, s, o = this,
                u = this.options;
            if (this.element.addClass("ui-resizable"), e.extend(this, {
                _aspectRatio: !!u.aspectRatio,
                aspectRatio: u.aspectRatio,
                originalElement: this.element,
                _proportionallyResizeElements: [],
                _helper: u.helper || u.ghost || u.animate ? u.helper || "ui-resizable-helper" : null
            }), this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i) && (this.element.wrap(e("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
                position: this.element.css("position"),
                width: this.element.outerWidth(),
                height: this.element.outerHeight(),
                top: this.element.css("top"),
                left: this.element.css("left")
            })), this.element = this.element.parent().data("ui-resizable", this.element.data("ui-resizable")), this.elementIsWrapper = !0, this.element.css({
                marginLeft: this.originalElement.css("marginLeft"),
                marginTop: this.originalElement.css("marginTop"),
                marginRight: this.originalElement.css("marginRight"),
                marginBottom: this.originalElement.css("marginBottom")
            }), this.originalElement.css({
                marginLeft: 0,
                marginTop: 0,
                marginRight: 0,
                marginBottom: 0
            }), this.originalResizeStyle = this.originalElement.css("resize"), this.originalElement.css("resize", "none"), this._proportionallyResizeElements.push(this.originalElement.css({
                position: "static",
                zoom: 1,
                display: "block"
            })), this.originalElement.css({
                margin: this.originalElement.css("margin")
            }), this._proportionallyResize()), this.handles = u.handles || (e(".ui-resizable-handle", this.element).length ? {
                n: ".ui-resizable-n",
                e: ".ui-resizable-e",
                s: ".ui-resizable-s",
                w: ".ui-resizable-w",
                se: ".ui-resizable-se",
                sw: ".ui-resizable-sw",
                ne: ".ui-resizable-ne",
                nw: ".ui-resizable-nw"
            } : "e,s,se"), this.handles.constructor === String)
                for ("all" === this.handles && (this.handles = "n,e,s,w,se,sw,ne,nw"), t = this.handles.split(","), this.handles = {}, n = 0; n < t.length; n++) r = e.trim(t[n]), s = "ui-resizable-" + r, i = e("<div class='ui-resizable-handle " + s + "'></div>"), i.css({
                    zIndex: u.zIndex
                }), "se" === r && i.addClass("ui-icon ui-icon-gripsmall-diagonal-se"), this.handles[r] = ".ui-resizable-" + r, this.element.append(i);
            this._renderAxis = function (t) {
                var n, r, i, s;
                t = t || this.element;
                for (n in this.handles) this.handles[n].constructor === String && (this.handles[n] = e(this.handles[n], this.element).show()), this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i) && (r = e(this.handles[n], this.element), s = /sw|ne|nw|se|n|s/.test(n) ? r.outerHeight() : r.outerWidth(), i = ["padding", /ne|nw|n/.test(n) ? "Top" : /se|sw|s/.test(n) ? "Bottom" : /^e$/.test(n) ? "Right" : "Left"].join(""), t.css(i, s), this._proportionallyResize()), e(this.handles[n]).length
            }, this._renderAxis(this.element), this._handles = e(".ui-resizable-handle", this.element).disableSelection(), this._handles.mouseover(function () {
                o.resizing || (this.className && (i = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)), o.axis = i && i[1] ? i[1] : "se")
            }), u.autoHide && (this._handles.hide(), e(this.element).addClass("ui-resizable-autohide").mouseenter(function () {
                u.disabled || (e(this).removeClass("ui-resizable-autohide"), o._handles.show())
            }).mouseleave(function () {
                u.disabled || o.resizing || (e(this).addClass("ui-resizable-autohide"), o._handles.hide())
            })), this._mouseInit()
        },
        _destroy: function () {
            this._mouseDestroy();
            var t, n = function (t) {
                e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()
            };
            return this.elementIsWrapper && (n(this.element), t = this.element, this.originalElement.css({
                position: t.css("position"),
                width: t.outerWidth(),
                height: t.outerHeight(),
                top: t.css("top"),
                left: t.css("left")
            }).insertAfter(t), t.remove()), this.originalElement.css("resize", this.originalResizeStyle), n(this.originalElement), this
        },
        _mouseCapture: function (t) {
            var n, r, i = !1;
            for (n in this.handles) r = e(this.handles[n])[0], (r === t.target || e.contains(r, t.target)) && (i = !0);
            return !this.options.disabled && i
        },
        _mouseStart: function (t) {
            var r, i, s, o = this.options,
                u = this.element.position(),
                a = this.element;
            return this.resizing = !0, /absolute/.test(a.css("position")) ? a.css({
                position: "absolute",
                top: a.css("top"),
                left: a.css("left")
            }) : a.is(".ui-draggable") && a.css({
                position: "absolute",
                top: u.top,
                left: u.left
            }), this._renderProxy(), r = n(this.helper.css("left")), i = n(this.helper.css("top")), o.containment && (r += e(o.containment).scrollLeft() || 0, i += e(o.containment).scrollTop() || 0), this.offset = this.helper.offset(), this.position = {
                left: r,
                top: i
            }, this.size = this._helper ? {
                width: a.outerWidth(),
                height: a.outerHeight()
            } : {
                width: a.width(),
                height: a.height()
            }, this.originalSize = this._helper ? {
                width: a.outerWidth(),
                height: a.outerHeight()
            } : {
                width: a.width(),
                height: a.height()
            }, this.originalPosition = {
                left: r,
                top: i
            }, this.sizeDiff = {
                width: a.outerWidth() - a.width(),
                height: a.outerHeight() - a.height()
            }, this.originalMousePosition = {
                left: t.pageX,
                top: t.pageY
            }, this.aspectRatio = "number" == typeof o.aspectRatio ? o.aspectRatio : this.originalSize.width / this.originalSize.height || 1, s = e(".ui-resizable-" + this.axis).css("cursor"), e("body").css("cursor", "auto" === s ? this.axis + "-resize" : s), a.addClass("ui-resizable-resizing"), this._propagate("start", t), !0
        },
        _mouseDrag: function (t) {
            var n, r = this.helper,
                i = {},
                s = this.originalMousePosition,
                o = this.axis,
                u = this.position.top,
                a = this.position.left,
                f = this.size.width,
                l = this.size.height,
                c = t.pageX - s.left || 0,
                h = t.pageY - s.top || 0,
                p = this._change[o];
            return p ? (n = p.apply(this, [t, c, h]), this._updateVirtualBoundaries(t.shiftKey), (this._aspectRatio || t.shiftKey) && (n = this._updateRatio(n, t)), n = this._respectSize(n, t), this._updateCache(n), this._propagate("resize", t), this.position.top !== u && (i.top = this.position.top + "px"), this.position.left !== a && (i.left = this.position.left + "px"), this.size.width !== f && (i.width = this.size.width + "px"), this.size.height !== l && (i.height = this.size.height + "px"), r.css(i), !this._helper && this._proportionallyResizeElements.length && this._proportionallyResize(), e.isEmptyObject(i) || this._trigger("resize", t, this.ui()), !1) : !1
        },
        _mouseStop: function (t) {
            this.resizing = !1;
            var n, r, i, s, o, u, a, f = this.options,
                l = this;
            return this._helper && (n = this._proportionallyResizeElements, r = n.length && /textarea/i.test(n[0].nodeName), i = r && e.ui.hasScroll(n[0], "left") ? 0 : l.sizeDiff.height, s = r ? 0 : l.sizeDiff.width, o = {
                width: l.helper.width() - s,
                height: l.helper.height() - i
            }, u = parseInt(l.element.css("left"), 10) + (l.position.left - l.originalPosition.left) || null, a = parseInt(l.element.css("top"), 10) + (l.position.top - l.originalPosition.top) || null, f.animate || this.element.css(e.extend(o, {
                top: a,
                left: u
            })), l.helper.height(l.size.height), l.helper.width(l.size.width), this._helper && !f.animate && this._proportionallyResize()), e("body").css("cursor", "auto"), this.element.removeClass("ui-resizable-resizing"), this._propagate("stop", t), this._helper && this.helper.remove(), !1
        },
        _updateVirtualBoundaries: function (e) {
            var t, n, i, s, o, u = this.options;
            o = {
                minWidth: r(u.minWidth) ? u.minWidth : 0,
                maxWidth: r(u.maxWidth) ? u.maxWidth : 1 / 0,
                minHeight: r(u.minHeight) ? u.minHeight : 0,
                maxHeight: r(u.maxHeight) ? u.maxHeight : 1 / 0
            }, (this._aspectRatio || e) && (t = o.minHeight * this.aspectRatio, i = o.minWidth / this.aspectRatio, n = o.maxHeight * this.aspectRatio, s = o.maxWidth / this.aspectRatio, t > o.minWidth && (o.minWidth = t), i > o.minHeight && (o.minHeight = i), n < o.maxWidth && (o.maxWidth = n), s < o.maxHeight && (o.maxHeight = s)), this._vBoundaries = o
        },
        _updateCache: function (e) {
            this.offset = this.helper.offset(), r(e.left) && (this.position.left = e.left), r(e.top) && (this.position.top = e.top), r(e.height) && (this.size.height = e.height), r(e.width) && (this.size.width = e.width)
        },
        _updateRatio: function (e) {
            var t = this.position,
                n = this.size,
                i = this.axis;
            return r(e.height) ? e.width = e.height * this.aspectRatio : r(e.width) && (e.height = e.width / this.aspectRatio), "sw" === i && (e.left = t.left + (n.width - e.width), e.top = null), "nw" === i && (e.top = t.top + (n.height - e.height), e.left = t.left + (n.width - e.width)), e
        },
        _respectSize: function (e) {
            var t = this._vBoundaries,
                n = this.axis,
                i = r(e.width) && t.maxWidth && t.maxWidth < e.width,
                s = r(e.height) && t.maxHeight && t.maxHeight < e.height,
                o = r(e.width) && t.minWidth && t.minWidth > e.width,
                u = r(e.height) && t.minHeight && t.minHeight > e.height,
                a = this.originalPosition.left + this.originalSize.width,
                f = this.position.top + this.size.height,
                l = /sw|nw|w/.test(n),
                c = /nw|ne|n/.test(n);
            return o && (e.width = t.minWidth), u && (e.height = t.minHeight), i && (e.width = t.maxWidth), s && (e.height = t.maxHeight), o && l && (e.left = a - t.minWidth), i && l && (e.left = a - t.maxWidth), u && c && (e.top = f - t.minHeight), s && c && (e.top = f - t.maxHeight), e.width || e.height || e.left || !e.top ? !e.width && !e.height && !e.top && e.left && (e.left = null) : e.top = null, e
        },
        _proportionallyResize: function () {
            if (this._proportionallyResizeElements.length) {
                var e, t, n, r, i, s = this.helper || this.element;
                for (e = 0; e < this._proportionallyResizeElements.length; e++) {
                    if (i = this._proportionallyResizeElements[e], !this.borderDif)
                        for (this.borderDif = [], n = [i.css("borderTopWidth"), i.css("borderRightWidth"), i.css("borderBottomWidth"), i.css("borderLeftWidth")], r = [i.css("paddingTop"), i.css("paddingRight"), i.css("paddingBottom"), i.css("paddingLeft")], t = 0; t < n.length; t++) this.borderDif[t] = (parseInt(n[t], 10) || 0) + (parseInt(r[t], 10) || 0);
                    i.css({
                        height: s.height() - this.borderDif[0] - this.borderDif[2] || 0,
                        width: s.width() - this.borderDif[1] - this.borderDif[3] || 0
                    })
                }
            }
        },
        _renderProxy: function () {
            var t = this.element,
                n = this.options;
            this.elementOffset = t.offset(), this._helper ? (this.helper = this.helper || e("<div style='overflow:hidden;'></div>"), this.helper.addClass(this._helper).css({
                width: this.element.outerWidth() - 1,
                height: this.element.outerHeight() - 1,
                position: "absolute",
                left: this.elementOffset.left + "px",
                top: this.elementOffset.top + "px",
                zIndex: ++n.zIndex
            }), this.helper.appendTo("body").disableSelection()) : this.helper = this.element
        },
        _change: {
            e: function (e, t) {
                return {
                    width: this.originalSize.width + t
                }
            },
            w: function (e, t) {
                var n = this.originalSize,
                    r = this.originalPosition;
                return {
                    left: r.left + t,
                    width: n.width - t
                }
            },
            n: function (e, t, n) {
                var r = this.originalSize,
                    i = this.originalPosition;
                return {
                    top: i.top + n,
                    height: r.height - n
                }
            },
            s: function (e, t, n) {
                return {
                    height: this.originalSize.height + n
                }
            },
            se: function (t, n, r) {
                return e.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [t, n, r]))
            },
            sw: function (t, n, r) {
                return e.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [t, n, r]))
            },
            ne: function (t, n, r) {
                return e.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [t, n, r]))
            },
            nw: function (t, n, r) {
                return e.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [t, n, r]))
            }
        },
        _propagate: function (t, n) {
            e.ui.plugin.call(this, t, [n, this.ui()]), "resize" !== t && this._trigger(t, n, this.ui())
        },
        plugins: {},
        ui: function () {
            return {
                originalElement: this.originalElement,
                element: this.element,
                helper: this.helper,
                position: this.position,
                size: this.size,
                originalSize: this.originalSize,
                originalPosition: this.originalPosition
            }
        }
    }), e.ui.plugin.add("resizable", "animate", {
        stop: function (t) {
            var n = e(this).data("ui-resizable"),
                r = n.options,
                i = n._proportionallyResizeElements,
                s = i.length && /textarea/i.test(i[0].nodeName),
                o = s && e.ui.hasScroll(i[0], "left") ? 0 : n.sizeDiff.height,
                u = s ? 0 : n.sizeDiff.width,
                a = {
                    width: n.size.width - u,
                    height: n.size.height - o
                },
                f = parseInt(n.element.css("left"), 10) + (n.position.left - n.originalPosition.left) || null,
                l = parseInt(n.element.css("top"), 10) + (n.position.top - n.originalPosition.top) || null;
            n.element.animate(e.extend(a, l && f ? {
                top: l,
                left: f
            } : {}), {
                duration: r.animateDuration,
                easing: r.animateEasing,
                step: function () {
                    var r = {
                        width: parseInt(n.element.css("width"), 10),
                        height: parseInt(n.element.css("height"), 10),
                        top: parseInt(n.element.css("top"), 10),
                        left: parseInt(n.element.css("left"), 10)
                    };
                    i && i.length && e(i[0]).css({
                        width: r.width,
                        height: r.height
                    }), n._updateCache(r), n._propagate("resize", t)
                }
            })
        }
    }), e.ui.plugin.add("resizable", "containment", {
        start: function () {
            var t, r, i, s, o, u, a, f = e(this).data("ui-resizable"),
                l = f.options,
                c = f.element,
                h = l.containment,
                p = h instanceof e ? h.get(0) : /parent/.test(h) ? c.parent().get(0) : h;
            p && (f.containerElement = e(p), /document/.test(h) || h === document ? (f.containerOffset = {
                left: 0,
                top: 0
            }, f.containerPosition = {
                left: 0,
                top: 0
            }, f.parentData = {
                element: e(document),
                left: 0,
                top: 0,
                width: e(document).width(),
                height: e(document).height() || document.body.parentNode.scrollHeight
            }) : (t = e(p), r = [], e(["Top", "Right", "Left", "Bottom"]).each(function (e, i) {
                r[e] = n(t.css("padding" + i))
            }), f.containerOffset = t.offset(), f.containerPosition = t.position(), f.containerSize = {
                height: t.innerHeight() - r[3],
                width: t.innerWidth() - r[1]
            }, i = f.containerOffset, s = f.containerSize.height, o = f.containerSize.width, u = e.ui.hasScroll(p, "left") ? p.scrollWidth : o, a = e.ui.hasScroll(p) ? p.scrollHeight : s, f.parentData = {
                element: p,
                left: i.left,
                top: i.top,
                width: u,
                height: a
            }))
        },
        resize: function (t) {
            var n, r, i, s, o = e(this).data("ui-resizable"),
                u = o.options,
                a = o.containerOffset,
                f = o.position,
                l = o._aspectRatio || t.shiftKey,
                c = {
                    top: 0,
                    left: 0
                },
                h = o.containerElement;
            h[0] !== document && /static/.test(h.css("position")) && (c = a), f.left < (o._helper ? a.left : 0) && (o.size.width = o.size.width + (o._helper ? o.position.left - a.left : o.position.left - c.left), l && (o.size.height = o.size.width / o.aspectRatio), o.position.left = u.helper ? a.left : 0), f.top < (o._helper ? a.top : 0) && (o.size.height = o.size.height + (o._helper ? o.position.top - a.top : o.position.top), l && (o.size.width = o.size.height * o.aspectRatio), o.position.top = o._helper ? a.top : 0), o.offset.left = o.parentData.left + o.position.left, o.offset.top = o.parentData.top + o.position.top, n = Math.abs((o._helper ? o.offset.left - c.left : o.offset.left - c.left) + o.sizeDiff.width), r = Math.abs((o._helper ? o.offset.top - c.top : o.offset.top - a.top) + o.sizeDiff.height), i = o.containerElement.get(0) === o.element.parent().get(0), s = /relative|absolute/.test(o.containerElement.css("position")), i && s && (n -= o.parentData.left), n + o.size.width >= o.parentData.width && (o.size.width = o.parentData.width - n, l && (o.size.height = o.size.width / o.aspectRatio)), r + o.size.height >= o.parentData.height && (o.size.height = o.parentData.height - r, l && (o.size.width = o.size.height * o.aspectRatio))
        },
        stop: function () {
            var t = e(this).data("ui-resizable"),
                n = t.options,
                r = t.containerOffset,
                i = t.containerPosition,
                s = t.containerElement,
                o = e(t.helper),
                u = o.offset(),
                a = o.outerWidth() - t.sizeDiff.width,
                f = o.outerHeight() - t.sizeDiff.height;
            t._helper && !n.animate && /relative/.test(s.css("position")) && e(this).css({
                left: u.left - i.left - r.left,
                width: a,
                height: f
            }), t._helper && !n.animate && /static/.test(s.css("position")) && e(this).css({
                left: u.left - i.left - r.left,
                width: a,
                height: f
            })
        }
    }), e.ui.plugin.add("resizable", "alsoResize", {
        start: function () {
            var t = e(this).data("ui-resizable"),
                n = t.options,
                r = function (t) {
                    e(t).each(function () {
                        var t = e(this);
                        t.data("ui-resizable-alsoresize", {
                            width: parseInt(t.width(), 10),
                            height: parseInt(t.height(), 10),
                            left: parseInt(t.css("left"), 10),
                            top: parseInt(t.css("top"), 10)
                        })
                    })
                };
            "object" != typeof n.alsoResize || n.alsoResize.parentNode ? r(n.alsoResize) : n.alsoResize.length ? (n.alsoResize = n.alsoResize[0], r(n.alsoResize)) : e.each(n.alsoResize, function (e) {
                r(e)
            })
        },
        resize: function (t, n) {
            var r = e(this).data("ui-resizable"),
                i = r.options,
                s = r.originalSize,
                o = r.originalPosition,
                u = {
                    height: r.size.height - s.height || 0,
                    width: r.size.width - s.width || 0,
                    top: r.position.top - o.top || 0,
                    left: r.position.left - o.left || 0
                },
                a = function (t, r) {
                    e(t).each(function () {
                        var t = e(this),
                            i = e(this).data("ui-resizable-alsoresize"),
                            s = {},
                            o = r && r.length ? r : t.parents(n.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"];
                        e.each(o, function (e, t) {
                            var n = (i[t] || 0) + (u[t] || 0);
                            n && n >= 0 && (s[t] = n || null)
                        }), t.css(s)
                    })
                };
            "object" != typeof i.alsoResize || i.alsoResize.nodeType ? a(i.alsoResize) : e.each(i.alsoResize, function (e, t) {
                a(e, t)
            })
        },
        stop: function () {
            e(this).removeData("resizable-alsoresize")
        }
    }), e.ui.plugin.add("resizable", "ghost", {
        start: function () {
            var t = e(this).data("ui-resizable"),
                n = t.options,
                r = t.size;
            t.ghost = t.originalElement.clone(), t.ghost.css({
                opacity: .25,
                display: "block",
                position: "relative",
                height: r.height,
                width: r.width,
                margin: 0,
                left: 0,
                top: 0
            }).addClass("ui-resizable-ghost").addClass("string" == typeof n.ghost ? n.ghost : ""), t.ghost.appendTo(t.helper)
        },
        resize: function () {
            var t = e(this).data("ui-resizable");
            t.ghost && t.ghost.css({
                position: "relative",
                height: t.size.height,
                width: t.size.width
            })
        },
        stop: function () {
            var t = e(this).data("ui-resizable");
            t.ghost && t.helper && t.helper.get(0).removeChild(t.ghost.get(0))
        }
    }), e.ui.plugin.add("resizable", "grid", {
        resize: function () {
            var t = e(this).data("ui-resizable"),
                n = t.options,
                r = t.size,
                i = t.originalSize,
                s = t.originalPosition,
                o = t.axis,
                u = "number" == typeof n.grid ? [n.grid, n.grid] : n.grid,
                a = u[0] || 1,
                f = u[1] || 1,
                l = Math.round((r.width - i.width) / a) * a,
                c = Math.round((r.height - i.height) / f) * f,
                h = i.width + l,
                p = i.height + c,
                d = n.maxWidth && n.maxWidth < h,
                v = n.maxHeight && n.maxHeight < p,
                m = n.minWidth && n.minWidth > h,
                g = n.minHeight && n.minHeight > p;
            n.grid = u, m && (h += a), g && (p += f), d && (h -= a), v && (p -= f), /^(se|s|e)$/.test(o) ? (t.size.width = h, t.size.height = p) : /^(ne)$/.test(o) ? (t.size.width = h, t.size.height = p, t.position.top = s.top - c) : /^(sw)$/.test(o) ? (t.size.width = h, t.size.height = p, t.position.left = s.left - l) : (t.size.width = h, t.size.height = p, t.position.top = s.top - c, t.position.left = s.left - l)
        }
    })
}(jQuery),
function (e) {
    e.widget("ui.selectable", e.ui.mouse, {
        version: "1.10.1",
        options: {
            appendTo: "body",
            autoRefresh: !0,
            distance: 0,
            filter: "*",
            tolerance: "touch",
            selected: null,
            selecting: null,
            start: null,
            stop: null,
            unselected: null,
            unselecting: null
        },
        _create: function () {
            var t, n = this;
            this.element.addClass("ui-selectable"), this.dragged = !1, this.refresh = function () {
                t = e(n.options.filter, n.element[0]), t.addClass("ui-selectee"), t.each(function () {
                    var t = e(this),
                        n = t.offset();
                    e.data(this, "selectable-item", {
                        element: this,
                        $element: t,
                        left: n.left,
                        top: n.top,
                        right: n.left + t.outerWidth(),
                        bottom: n.top + t.outerHeight(),
                        startselected: !1,
                        selected: t.hasClass("ui-selected"),
                        selecting: t.hasClass("ui-selecting"),
                        unselecting: t.hasClass("ui-unselecting")
                    })
                })
            }, this.refresh(), this.selectees = t.addClass("ui-selectee"), this._mouseInit(), this.helper = e("<div class='ui-selectable-helper'></div>")
        },
        _destroy: function () {
            this.selectees.removeClass("ui-selectee").removeData("selectable-item"), this.element.removeClass("ui-selectable ui-selectable-disabled"), this._mouseDestroy()
        },
        _mouseStart: function (t) {
            var n = this,
                r = this.options;
            this.opos = [t.pageX, t.pageY], this.options.disabled || (this.selectees = e(r.filter, this.element[0]), this._trigger("start", t), e(r.appendTo).append(this.helper), this.helper.css({
                left: t.pageX,
                top: t.pageY,
                width: 0,
                height: 0
            }), r.autoRefresh && this.refresh(), this.selectees.filter(".ui-selected").each(function () {
                var r = e.data(this, "selectable-item");
                r.startselected = !0, !t.metaKey && !t.ctrlKey && (r.$element.removeClass("ui-selected"), r.selected = !1, r.$element.addClass("ui-unselecting"), r.unselecting = !0, n._trigger("unselecting", t, {
                    unselecting: r.element
                }))
            }), e(t.target).parents().addBack().each(function () {
                var r, i = e.data(this, "selectable-item");
                return i ? (r = !t.metaKey && !t.ctrlKey || !i.$element.hasClass("ui-selected"), i.$element.removeClass(r ? "ui-unselecting" : "ui-selected").addClass(r ? "ui-selecting" : "ui-unselecting"), i.unselecting = !r, i.selecting = r, i.selected = r, r ? n._trigger("selecting", t, {
                    selecting: i.element
                }) : n._trigger("unselecting", t, {
                    unselecting: i.element
                }), !1) : void 0
            }))
        },
        _mouseDrag: function (t) {
            if (this.dragged = !0, !this.options.disabled) {
                var n, r = this,
                    i = this.options,
                    s = this.opos[0],
                    o = this.opos[1],
                    u = t.pageX,
                    a = t.pageY;
                return s > u && (n = u, u = s, s = n), o > a && (n = a, a = o, o = n), this.helper.css({
                    left: s,
                    top: o,
                    width: u - s,
                    height: a - o
                }), this.selectees.each(function () {
                    var n = e.data(this, "selectable-item"),
                        f = !1;
                    n && n.element !== r.element[0] && ("touch" === i.tolerance ? f = !(n.left > u || n.right < s || n.top > a || n.bottom < o) : "fit" === i.tolerance && (f = n.left > s && n.right < u && n.top > o && n.bottom < a), f ? (n.selected && (n.$element.removeClass("ui-selected"), n.selected = !1), n.unselecting && (n.$element.removeClass("ui-unselecting"), n.unselecting = !1), n.selecting || (n.$element.addClass("ui-selecting"), n.selecting = !0, r._trigger("selecting", t, {
                        selecting: n.element
                    }))) : (n.selecting && ((t.metaKey || t.ctrlKey) && n.startselected ? (n.$element.removeClass("ui-selecting"), n.selecting = !1, n.$element.addClass("ui-selected"), n.selected = !0) : (n.$element.removeClass("ui-selecting"), n.selecting = !1, n.startselected && (n.$element.addClass("ui-unselecting"), n.unselecting = !0), r._trigger("unselecting", t, {
                        unselecting: n.element
                    }))), n.selected && !t.metaKey && !t.ctrlKey && !n.startselected && (n.$element.removeClass("ui-selected"), n.selected = !1, n.$element.addClass("ui-unselecting"), n.unselecting = !0, r._trigger("unselecting", t, {
                        unselecting: n.element
                    }))))
                }), !1
            }
        },
        _mouseStop: function (t) {
            var n = this;
            return this.dragged = !1, e(".ui-unselecting", this.element[0]).each(function () {
                var r = e.data(this, "selectable-item");
                r.$element.removeClass("ui-unselecting"), r.unselecting = !1, r.startselected = !1, n._trigger("unselected", t, {
                    unselected: r.element
                })
            }), e(".ui-selecting", this.element[0]).each(function () {
                var r = e.data(this, "selectable-item");
                r.$element.removeClass("ui-selecting").addClass("ui-selected"), r.selecting = !1, r.selected = !0, r.startselected = !0, n._trigger("selected", t, {
                    selected: r.element
                })
            }), this._trigger("stop", t), this.helper.remove(), !1
        }
    })
}(jQuery),
function (e) {
    var n = 5;
    e.widget("ui.slider", e.ui.mouse, {
        version: "1.10.1",
        widgetEventPrefix: "slide",
        options: {
            animate: !1,
            distance: 0,
            max: 100,
            min: 0,
            orientation: "horizontal",
            range: !1,
            step: 1,
            value: 0,
            values: null,
            change: null,
            slide: null,
            start: null,
            stop: null
        },
        _create: function () {
            this._keySliding = !1, this._mouseSliding = !1, this._animateOff = !0, this._handleIndex = null, this._detectOrientation(), this._mouseInit(), this.element.addClass("ui-slider ui-slider-" + this.orientation + " ui-widget ui-widget-content ui-corner-all"), this._refresh(), this._setOption("disabled", this.options.disabled), this._animateOff = !1
        },
        _refresh: function () {
            this._createRange(), this._createHandles(), this._setupEvents(), this._refreshValue()
        },
        _createHandles: function () {
            var t, n, r = this.options,
                i = this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),
                s = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
                o = [];
            for (n = r.values && r.values.length || 1, i.length > n && (i.slice(n).remove(), i = i.slice(0, n)), t = i.length; n > t; t++) o.push(s);
            this.handles = i.add(e(o.join("")).appendTo(this.element)), this.handle = this.handles.eq(0), this.handles.each(function (t) {
                e(this).data("ui-slider-handle-index", t)
            })
        },
        _createRange: function () {
            var t = this.options,
                n = "";
            t.range ? (t.range === !0 && (t.values ? t.values.length && 2 !== t.values.length ? t.values = [t.values[0], t.values[0]] : e.isArray(t.values) && (t.values = t.values.slice(0)) : t.values = [this._valueMin(), this._valueMin()]), this.range && this.range.length ? this.range.removeClass("ui-slider-range-min ui-slider-range-max").css({
                left: "",
                bottom: ""
            }) : (this.range = e("<div></div>").appendTo(this.element), n = "ui-slider-range ui-widget-header ui-corner-all"), this.range.addClass(n + ("min" === t.range || "max" === t.range ? " ui-slider-range-" + t.range : ""))) : this.range = e([])
        },
        _setupEvents: function () {
            var e = this.handles.add(this.range).filter("a");
            this._off(e), this._on(e, this._handleEvents), this._hoverable(e), this._focusable(e)
        },
        _destroy: function () {
            this.handles.remove(), this.range.remove(), this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-widget ui-widget-content ui-corner-all"), this._mouseDestroy()
        },
        _mouseCapture: function (t) {
            var n, r, i, s, o, u, a, f, l = this,
                c = this.options;
            return c.disabled ? !1 : (this.elementSize = {
                width: this.element.outerWidth(),
                height: this.element.outerHeight()
            }, this.elementOffset = this.element.offset(), n = {
                x: t.pageX,
                y: t.pageY
            }, r = this._normValueFromMouse(n), i = this._valueMax() - this._valueMin() + 1, this.handles.each(function (t) {
                var n = Math.abs(r - l.values(t));
                (i > n || i === n && (t === l._lastChangedValue || l.values(t) === c.min)) && (i = n, s = e(this), o = t)
            }), u = this._start(t, o), u === !1 ? !1 : (this._mouseSliding = !0, this._handleIndex = o, s.addClass("ui-state-active").focus(), a = s.offset(), f = !e(t.target).parents().addBack().is(".ui-slider-handle"), this._clickOffset = f ? {
                left: 0,
                top: 0
            } : {
                left: t.pageX - a.left - s.width() / 2,
                top: t.pageY - a.top - s.height() / 2 - (parseInt(s.css("borderTopWidth"), 10) || 0) - (parseInt(s.css("borderBottomWidth"), 10) || 0) + (parseInt(s.css("marginTop"), 10) || 0)
            }, this.handles.hasClass("ui-state-hover") || this._slide(t, o, r), this._animateOff = !0, !0))
        },
        _mouseStart: function () {
            return !0
        },
        _mouseDrag: function (e) {
            var t = {
                    x: e.pageX,
                    y: e.pageY
                },
                n = this._normValueFromMouse(t);
            return this._slide(e, this._handleIndex, n), !1
        },
        _mouseStop: function (e) {
            return this.handles.removeClass("ui-state-active"), this._mouseSliding = !1, this._stop(e, this._handleIndex), this._change(e, this._handleIndex), this._handleIndex = null, this._clickOffset = null, this._animateOff = !1, !1
        },
        _detectOrientation: function () {
            this.orientation = "vertical" === this.options.orientation ? "vertical" : "horizontal"
        },
        _normValueFromMouse: function (e) {
            var t, n, r, i, s;
            return "horizontal" === this.orientation ? (t = this.elementSize.width, n = e.x - this.elementOffset.left - (this._clickOffset ? this._clickOffset.left : 0)) : (t = this.elementSize.height, n = e.y - this.elementOffset.top - (this._clickOffset ? this._clickOffset.top : 0)), r = n / t, r > 1 && (r = 1), 0 > r && (r = 0), "vertical" === this.orientation && (r = 1 - r), i = this._valueMax() - this._valueMin(), s = this._valueMin() + r * i, this._trimAlignValue(s)
        },
        _start: function (e, t) {
            var n = {
                handle: this.handles[t],
                value: this.value()
            };
            return this.options.values && this.options.values.length && (n.value = this.values(t), n.values = this.values()), this._trigger("start", e, n)
        },
        _slide: function (e, t, n) {
            var r, i, s;
            this.options.values && this.options.values.length ? (r = this.values(t ? 0 : 1), 2 === this.options.values.length && this.options.range === !0 && (0 === t && n > r || 1 === t && r > n) && (n = r), n !== this.values(t) && (i = this.values(), i[t] = n, s = this._trigger("slide", e, {
                handle: this.handles[t],
                value: n,
                values: i
            }), r = this.values(t ? 0 : 1), s !== !1 && this.values(t, n, !0))) : n !== this.value() && (s = this._trigger("slide", e, {
                handle: this.handles[t],
                value: n
            }), s !== !1 && this.value(n))
        },
        _stop: function (e, t) {
            var n = {
                handle: this.handles[t],
                value: this.value()
            };
            this.options.values && this.options.values.length && (n.value = this.values(t), n.values = this.values()), this._trigger("stop", e, n)
        },
        _change: function (e, t) {
            if (!this._keySliding && !this._mouseSliding) {
                var n = {
                    handle: this.handles[t],
                    value: this.value()
                };
                this.options.values && this.options.values.length && (n.value = this.values(t), n.values = this.values()), this._lastChangedValue = t, this._trigger("change", e, n)
            }
        },
        value: function (e) {
            return arguments.length ? (this.options.value = this._trimAlignValue(e), this._refreshValue(), this._change(null, 0), void 0) : this._value()
        },
        values: function (t, n) {
            var r, i, s;
            if (arguments.length > 1) return this.options.values[t] = this._trimAlignValue(n), this._refreshValue(), this._change(null, t), void 0;
            if (!arguments.length) return this._values();
            if (!e.isArray(arguments[0])) return this.options.values && this.options.values.length ? this._values(t) : this.value();
            for (r = this.options.values, i = arguments[0], s = 0; s < r.length; s += 1) r[s] = this._trimAlignValue(i[s]), this._change(null, s);
            this._refreshValue()
        },
        _setOption: function (t, n) {
            var r, i = 0;
            switch ("range" === t && this.options.range === !0 && ("min" === n ? (this.options.value = this._values(0), this.options.values = null) : "max" === n && (this.options.value = this._values(this.options.values.length - 1), this.options.values = null)), e.isArray(this.options.values) && (i = this.options.values.length), e.Widget.prototype._setOption.apply(this, arguments), t) {
            case "orientation":
                this._detectOrientation(), this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-" + this.orientation), this._refreshValue();
                break;
            case "value":
                this._animateOff = !0, this._refreshValue(), this._change(null, 0), this._animateOff = !1;
                break;
            case "values":
                for (this._animateOff = !0, this._refreshValue(), r = 0; i > r; r += 1) this._change(null, r);
                this._animateOff = !1;
                break;
            case "min":
            case "max":
                this._animateOff = !0, this._refreshValue(), this._animateOff = !1;
                break;
            case "range":
                this._animateOff = !0, this._refresh(), this._animateOff = !1
            }
        },
        _value: function () {
            var e = this.options.value;
            return e = this._trimAlignValue(e)
        },
        _values: function (e) {
            var t, n, r;
            if (arguments.length) return t = this.options.values[e], t = this._trimAlignValue(t);
            if (this.options.values && this.options.values.length) {
                for (n = this.options.values.slice(), r = 0; r < n.length; r += 1) n[r] = this._trimAlignValue(n[r]);
                return n
            }
            return []
        },
        _trimAlignValue: function (e) {
            if (e <= this._valueMin()) return this._valueMin();
            if (e >= this._valueMax()) return this._valueMax();
            var t = this.options.step > 0 ? this.options.step : 1,
                n = (e - this._valueMin()) % t,
                r = e - n;
            return 2 * Math.abs(n) >= t && (r += n > 0 ? t : -t), parseFloat(r.toFixed(5))
        },
        _valueMin: function () {
            return this.options.min
        },
        _valueMax: function () {
            return this.options.max
        },
        _refreshValue: function () {
            var t, n, r, i, s, o = this.options.range,
                u = this.options,
                a = this,
                f = this._animateOff ? !1 : u.animate,
                l = {};
            this.options.values && this.options.values.length ? this.handles.each(function (r) {
                n = 100 * ((a.values(r) - a._valueMin()) / (a._valueMax() - a._valueMin())), l["horizontal" === a.orientation ? "left" : "bottom"] = n + "%", e(this).stop(1, 1)[f ? "animate" : "css"](l, u.animate), a.options.range === !0 && ("horizontal" === a.orientation ? (0 === r && a.range.stop(1, 1)[f ? "animate" : "css"]({
                    left: n + "%"
                }, u.animate), 1 === r && a.range[f ? "animate" : "css"]({
                    width: n - t + "%"
                }, {
                    queue: !1,
                    duration: u.animate
                })) : (0 === r && a.range.stop(1, 1)[f ? "animate" : "css"]({
                    bottom: n + "%"
                }, u.animate), 1 === r && a.range[f ? "animate" : "css"]({
                    height: n - t + "%"
                }, {
                    queue: !1,
                    duration: u.animate
                }))), t = n
            }) : (r = this.value(), i = this._valueMin(), s = this._valueMax(), n = s !== i ? 100 * ((r - i) / (s - i)) : 0, l["horizontal" === this.orientation ? "left" : "bottom"] = n + "%", this.handle.stop(1, 1)[f ? "animate" : "css"](l, u.animate), "min" === o && "horizontal" === this.orientation && this.range.stop(1, 1)[f ? "animate" : "css"]({
                width: n + "%"
            }, u.animate), "max" === o && "horizontal" === this.orientation && this.range[f ? "animate" : "css"]({
                width: 100 - n + "%"
            }, {
                queue: !1,
                duration: u.animate
            }), "min" === o && "vertical" === this.orientation && this.range.stop(1, 1)[f ? "animate" : "css"]({
                height: n + "%"
            }, u.animate), "max" === o && "vertical" === this.orientation && this.range[f ? "animate" : "css"]({
                height: 100 - n + "%"
            }, {
                queue: !1,
                duration: u.animate
            }))
        },
        _handleEvents: {
            keydown: function (t) {
                var r, i, s, o, u = e(t.target).data("ui-slider-handle-index");
                switch (t.keyCode) {
                case e.ui.keyCode.HOME:
                case e.ui.keyCode.END:
                case e.ui.keyCode.PAGE_UP:
                case e.ui.keyCode.PAGE_DOWN:
                case e.ui.keyCode.UP:
                case e.ui.keyCode.RIGHT:
                case e.ui.keyCode.DOWN:
                case e.ui.keyCode.LEFT:
                    if (t.preventDefault(), !this._keySliding && (this._keySliding = !0, e(t.target).addClass("ui-state-active"), r = this._start(t, u), r === !1)) return
                }
                switch (o = this.options.step, i = s = this.options.values && this.options.values.length ? this.values(u) : this.value(), t.keyCode) {
                case e.ui.keyCode.HOME:
                    s = this._valueMin();
                    break;
                case e.ui.keyCode.END:
                    s = this._valueMax();
                    break;
                case e.ui.keyCode.PAGE_UP:
                    s = this._trimAlignValue(i + (this._valueMax() - this._valueMin()) / n);
                    break;
                case e.ui.keyCode.PAGE_DOWN:
                    s = this._trimAlignValue(i - (this._valueMax() - this._valueMin()) / n);
                    break;
                case e.ui.keyCode.UP:
                case e.ui.keyCode.RIGHT:
                    if (i === this._valueMax()) return;
                    s = this._trimAlignValue(i + o);
                    break;
                case e.ui.keyCode.DOWN:
                case e.ui.keyCode.LEFT:
                    if (i === this._valueMin()) return;
                    s = this._trimAlignValue(i - o)
                }
                this._slide(t, u, s)
            },
            click: function (e) {
                e.preventDefault()
            },
            keyup: function (t) {
                var n = e(t.target).data("ui-slider-handle-index");
                this._keySliding && (this._keySliding = !1, this._stop(t, n), this._change(t, n), e(t.target).removeClass("ui-state-active"))
            }
        }
    })
}(jQuery),
function (e) {
    function n(e, t, n) {
        return e > t && t + n > e
    }
    e.widget("ui.sortable", e.ui.mouse, {
        version: "1.10.1",
        widgetEventPrefix: "sort",
        ready: !1,
        options: {
            appendTo: "parent",
            axis: !1,
            connectWith: !1,
            containment: !1,
            cursor: "auto",
            cursorAt: !1,
            dropOnEmpty: !0,
            forcePlaceholderSize: !1,
            forceHelperSize: !1,
            grid: !1,
            handle: !1,
            helper: "original",
            items: "> *",
            opacity: !1,
            placeholder: !1,
            revert: !1,
            scroll: !0,
            scrollSensitivity: 20,
            scrollSpeed: 20,
            scope: "default",
            tolerance: "intersect",
            zIndex: 1e3,
            activate: null,
            beforeStop: null,
            change: null,
            deactivate: null,
            out: null,
            over: null,
            receive: null,
            remove: null,
            sort: null,
            start: null,
            stop: null,
            update: null
        },
        _create: function () {
            var e = this.options;
            this.containerCache = {}, this.element.addClass("ui-sortable"), this.refresh(), this.floating = this.items.length ? "x" === e.axis || /left|right/.test(this.items[0].item.css("float")) || /inline|table-cell/.test(this.items[0].item.css("display")) : !1, this.offset = this.element.offset(), this._mouseInit(), this.ready = !0
        },
        _destroy: function () {
            this.element.removeClass("ui-sortable ui-sortable-disabled"), this._mouseDestroy();
            for (var e = this.items.length - 1; e >= 0; e--) this.items[e].item.removeData(this.widgetName + "-item");
            return this
        },
        _setOption: function (t, n) {
            "disabled" === t ? (this.options[t] = n, this.widget().toggleClass("ui-sortable-disabled", !!n)) : e.Widget.prototype._setOption.apply(this, arguments)
        },
        _mouseCapture: function (t, n) {
            var r = null,
                i = !1,
                s = this;
            return this.reverting ? !1 : this.options.disabled || "static" === this.options.type ? !1 : (this._refreshItems(t), e(t.target).parents().each(function () {
                return e.data(this, s.widgetName + "-item") === s ? (r = e(this), !1) : void 0
            }), e.data(t.target, s.widgetName + "-item") === s && (r = e(t.target)), r ? !this.options.handle || n || (e(this.options.handle, r).find("*").addBack().each(function () {
                this === t.target && (i = !0)
            }), i) ? (this.currentItem = r, this._removeCurrentsFromItems(), !0) : !1 : !1)
        },
        _mouseStart: function (t, n, r) {
            var i, s = this.options;
            if (this.currentContainer = this, this.refreshPositions(), this.helper = this._createHelper(t), this._cacheHelperProportions(), this._cacheMargins(), this.scrollParent = this.helper.scrollParent(), this.offset = this.currentItem.offset(), this.offset = {
                top: this.offset.top - this.margins.top,
                left: this.offset.left - this.margins.left
            }, e.extend(this.offset, {
                click: {
                    left: t.pageX - this.offset.left,
                    top: t.pageY - this.offset.top
                },
                parent: this._getParentOffset(),
                relative: this._getRelativeOffset()
            }), this.helper.css("position", "absolute"), this.cssPosition = this.helper.css("position"), this.originalPosition = this._generatePosition(t), this.originalPageX = t.pageX, this.originalPageY = t.pageY, s.cursorAt && this._adjustOffsetFromHelper(s.cursorAt), this.domPosition = {
                prev: this.currentItem.prev()[0],
                parent: this.currentItem.parent()[0]
            }, this.helper[0] !== this.currentItem[0] && this.currentItem.hide(), this._createPlaceholder(), s.containment && this._setContainment(), s.cursor && (e("body").css("cursor") && (this._storedCursor = e("body").css("cursor")), e("body").css("cursor", s.cursor)), s.opacity && (this.helper.css("opacity") && (this._storedOpacity = this.helper.css("opacity")), this.helper.css("opacity", s.opacity)), s.zIndex && (this.helper.css("zIndex") && (this._storedZIndex = this.helper.css("zIndex")), this.helper.css("zIndex", s.zIndex)), this.scrollParent[0] !== document && "HTML" !== this.scrollParent[0].tagName && (this.overflowOffset = this.scrollParent.offset()), this._trigger("start", t, this._uiHash()), this._preserveHelperProportions || this._cacheHelperProportions(), !r)
                for (i = this.containers.length - 1; i >= 0; i--) this.containers[i]._trigger("activate", t, this._uiHash(this));
            return e.ui.ddmanager && (e.ui.ddmanager.current = this), e.ui.ddmanager && !s.dropBehaviour && e.ui.ddmanager.prepareOffsets(this, t), this.dragging = !0, this.helper.addClass("ui-sortable-helper"), this._mouseDrag(t), !0
        },
        _mouseDrag: function (t) {
            var n, r, i, s, o = this.options,
                u = !1;
            for (this.position = this._generatePosition(t), this.positionAbs = this._convertPositionTo("absolute"), this.lastPositionAbs || (this.lastPositionAbs = this.positionAbs), this.options.scroll && (this.scrollParent[0] !== document && "HTML" !== this.scrollParent[0].tagName ? (this.overflowOffset.top + this.scrollParent[0].offsetHeight - t.pageY < o.scrollSensitivity ? this.scrollParent[0].scrollTop = u = this.scrollParent[0].scrollTop + o.scrollSpeed : t.pageY - this.overflowOffset.top < o.scrollSensitivity && (this.scrollParent[0].scrollTop = u = this.scrollParent[0].scrollTop - o.scrollSpeed), this.overflowOffset.left + this.scrollParent[0].offsetWidth - t.pageX < o.scrollSensitivity ? this.scrollParent[0].scrollLeft = u = this.scrollParent[0].scrollLeft + o.scrollSpeed : t.pageX - this.overflowOffset.left < o.scrollSensitivity && (this.scrollParent[0].scrollLeft = u = this.scrollParent[0].scrollLeft - o.scrollSpeed)) : (t.pageY - e(document).scrollTop() < o.scrollSensitivity ? u = e(document).scrollTop(e(document).scrollTop() - o.scrollSpeed) : e(window).height() - (t.pageY - e(document).scrollTop()) < o.scrollSensitivity && (u = e(document).scrollTop(e(document).scrollTop() + o.scrollSpeed)), t.pageX - e(document).scrollLeft() < o.scrollSensitivity ? u = e(document).scrollLeft(e(document).scrollLeft() - o.scrollSpeed) : e(window).width() - (t.pageX - e(document).scrollLeft()) < o.scrollSensitivity && (u = e(document).scrollLeft(e(document).scrollLeft() + o.scrollSpeed))), u !== !1 && e.ui.ddmanager && !o.dropBehaviour && e.ui.ddmanager.prepareOffsets(this, t)), this.positionAbs = this._convertPositionTo("absolute"), this.options.axis && "y" === this.options.axis || (this.helper[0].style.left = this.position.left + "px"), this.options.axis && "x" === this.options.axis || (this.helper[0].style.top = this.position.top + "px"), n = this.items.length - 1; n >= 0; n--)
                if (r = this.items[n], i = r.item[0], s = this._intersectsWithPointer(r), s && r.instance === this.currentContainer && i !== this.currentItem[0] && this.placeholder[1 === s ? "next" : "prev"]()[0] !== i && !e.contains(this.placeholder[0], i) && ("semi-dynamic" === this.options.type ? !e.contains(this.element[0], i) : !0)) {
                    if (this.direction = 1 === s ? "down" : "up", "pointer" !== this.options.tolerance && !this._intersectsWithSides(r)) break;
                    this._rearrange(t, r), this._trigger("change", t, this._uiHash());
                    break
                }
            return this._contactContainers(t), e.ui.ddmanager && e.ui.ddmanager.drag(this, t), this._trigger("sort", t, this._uiHash()), this.lastPositionAbs = this.positionAbs, !1
        },
        _mouseStop: function (t, n) {
            if (t) {
                if (e.ui.ddmanager && !this.options.dropBehaviour && e.ui.ddmanager.drop(this, t), this.options.revert) {
                    var r = this,
                        i = this.placeholder.offset();
                    this.reverting = !0, e(this.helper).animate({
                        left: i.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft),
                        top: i.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop)
                    }, parseInt(this.options.revert, 10) || 500, function () {
                        r._clear(t)
                    })
                } else this._clear(t, n);
                return !1
            }
        },
        cancel: function () {
            if (this.dragging) {
                this._mouseUp({
                    target: null
                }), "original" === this.options.helper ? this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper") : this.currentItem.show();
                for (var t = this.containers.length - 1; t >= 0; t--) this.containers[t]._trigger("deactivate", null, this._uiHash(this)), this.containers[t].containerCache.over && (this.containers[t]._trigger("out", null, this._uiHash(this)), this.containers[t].containerCache.over = 0)
            }
            return this.placeholder && (this.placeholder[0].parentNode && this.placeholder[0].parentNode.removeChild(this.placeholder[0]), "original" !== this.options.helper && this.helper && this.helper[0].parentNode && this.helper.remove(), e.extend(this, {
                helper: null,
                dragging: !1,
                reverting: !1,
                _noFinalSort: null
            }), this.domPosition.prev ? e(this.domPosition.prev).after(this.currentItem) : e(this.domPosition.parent).prepend(this.currentItem)), this
        },
        serialize: function (t) {
            var n = this._getItemsAsjQuery(t && t.connected),
                r = [];
            return t = t || {}, e(n).each(function () {
                var n = (e(t.item || this).attr(t.attribute || "id") || "").match(t.expression || /(.+)[\-=_](.+)/);
                n && r.push((t.key || n[1] + "[]") + "=" + (t.key && t.expression ? n[1] : n[2]))
            }), !r.length && t.key && r.push(t.key + "="), r.join("&")
        },
        toArray: function (t) {
            var n = this._getItemsAsjQuery(t && t.connected),
                r = [];
            return t = t || {}, n.each(function () {
                r.push(e(t.item || this).attr(t.attribute || "id") || "")
            }), r
        },
        _intersectsWith: function (e) {
            var t = this.positionAbs.left,
                n = t + this.helperProportions.width,
                r = this.positionAbs.top,
                i = r + this.helperProportions.height,
                s = e.left,
                o = s + e.width,
                u = e.top,
                a = u + e.height,
                f = this.offset.click.top,
                l = this.offset.click.left,
                c = r + f > u && a > r + f && t + l > s && o > t + l;
            return "pointer" === this.options.tolerance || this.options.forcePointerForContainers || "pointer" !== this.options.tolerance && this.helperProportions[this.floating ? "width" : "height"] > e[this.floating ? "width" : "height"] ? c : s < t + this.helperProportions.width / 2 && n - this.helperProportions.width / 2 < o && u < r + this.helperProportions.height / 2 && i - this.helperProportions.height / 2 < a
        },
        _intersectsWithPointer: function (e) {
            var t = "x" === this.options.axis || n(this.positionAbs.top + this.offset.click.top, e.top, e.height),
                r = "y" === this.options.axis || n(this.positionAbs.left + this.offset.click.left, e.left, e.width),
                i = t && r,
                s = this._getDragVerticalDirection(),
                o = this._getDragHorizontalDirection();
            return i ? this.floating ? o && "right" === o || "down" === s ? 2 : 1 : s && ("down" === s ? 2 : 1) : !1
        },
        _intersectsWithSides: function (e) {
            var t = n(this.positionAbs.top + this.offset.click.top, e.top + e.height / 2, e.height),
                r = n(this.positionAbs.left + this.offset.click.left, e.left + e.width / 2, e.width),
                i = this._getDragVerticalDirection(),
                s = this._getDragHorizontalDirection();
            return this.floating && s ? "right" === s && r || "left" === s && !r : i && ("down" === i && t || "up" === i && !t)
        },
        _getDragVerticalDirection: function () {
            var e = this.positionAbs.top - this.lastPositionAbs.top;
            return 0 !== e && (e > 0 ? "down" : "up")
        },
        _getDragHorizontalDirection: function () {
            var e = this.positionAbs.left - this.lastPositionAbs.left;
            return 0 !== e && (e > 0 ? "right" : "left")
        },
        refresh: function (e) {
            return this._refreshItems(e), this.refreshPositions(), this
        },
        _connectWith: function () {
            var e = this.options;
            return e.connectWith.constructor === String ? [e.connectWith] : e.connectWith
        },
        _getItemsAsjQuery: function (t) {
            var n, r, i, s, o = [],
                u = [],
                a = this._connectWith();
            if (a && t)
                for (n = a.length - 1; n >= 0; n--)
                    for (i = e(a[n]), r = i.length - 1; r >= 0; r--) s = e.data(i[r], this.widgetFullName), s && s !== this && !s.options.disabled && u.push([e.isFunction(s.options.items) ? s.options.items.call(s.element) : e(s.options.items, s.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), s]);
            for (u.push([e.isFunction(this.options.items) ? this.options.items.call(this.element, null, {
                options: this.options,
                item: this.currentItem
            }) : e(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]), n = u.length - 1; n >= 0; n--) u[n][0].each(function () {
                o.push(this)
            });
            return e(o)
        },
        _removeCurrentsFromItems: function () {
            var t = this.currentItem.find(":data(" + this.widgetName + "-item)");
            this.items = e.grep(this.items, function (e) {
                for (var n = 0; n < t.length; n++)
                    if (t[n] === e.item[0]) return !1;
                return !0
            })
        },
        _refreshItems: function (t) {
            this.items = [], this.containers = [this];
            var n, r, i, s, o, u, a, f, l = this.items,
                c = [
                    [e.isFunction(this.options.items) ? this.options.items.call(this.element[0], t, {
                        item: this.currentItem
                    }) : e(this.options.items, this.element), this]
                ],
                h = this._connectWith();
            if (h && this.ready)
                for (n = h.length - 1; n >= 0; n--)
                    for (i = e(h[n]), r = i.length - 1; r >= 0; r--) s = e.data(i[r], this.widgetFullName), s && s !== this && !s.options.disabled && (c.push([e.isFunction(s.options.items) ? s.options.items.call(s.element[0], t, {
                        item: this.currentItem
                    }) : e(s.options.items, s.element), s]), this.containers.push(s));
            for (n = c.length - 1; n >= 0; n--)
                for (o = c[n][1], u = c[n][0], r = 0, f = u.length; f > r; r++) a = e(u[r]), a.data(this.widgetName + "-item", o), l.push({
                    item: a,
                    instance: o,
                    width: 0,
                    height: 0,
                    left: 0,
                    top: 0
                })
        },
        refreshPositions: function (t) {
            this.offsetParent && this.helper && (this.offset.parent = this._getParentOffset());
            var n, r, i, s;
            for (n = this.items.length - 1; n >= 0; n--) r = this.items[n], r.instance !== this.currentContainer && this.currentContainer && r.item[0] !== this.currentItem[0] || (i = this.options.toleranceElement ? e(this.options.toleranceElement, r.item) : r.item, t || (r.width = i.outerWidth(), r.height = i.outerHeight()), s = i.offset(), r.left = s.left, r.top = s.top);
            if (this.options.custom && this.options.custom.refreshContainers) this.options.custom.refreshContainers.call(this);
            else
                for (n = this.containers.length - 1; n >= 0; n--) s = this.containers[n].element.offset(), this.containers[n].containerCache.left = s.left, this.containers[n].containerCache.top = s.top, this.containers[n].containerCache.width = this.containers[n].element.outerWidth(), this.containers[n].containerCache.height = this.containers[n].element.outerHeight();
            return this
        },
        _createPlaceholder: function (t) {
            t = t || this;
            var n, r = t.options;
            r.placeholder && r.placeholder.constructor !== String || (n = r.placeholder, r.placeholder = {
                element: function () {
                    var r = e(document.createElement(t.currentItem[0].nodeName)).addClass(n || t.currentItem[0].className + " ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];
                    return n || (r.style.visibility = "hidden"), r
                },
                update: function (e, i) {
                    (!n || r.forcePlaceholderSize) && (i.height() || i.height(t.currentItem.innerHeight() - parseInt(t.currentItem.css("paddingTop") || 0, 10) - parseInt(t.currentItem.css("paddingBottom") || 0, 10)), i.width() || i.width(t.currentItem.innerWidth() - parseInt(t.currentItem.css("paddingLeft") || 0, 10) - parseInt(t.currentItem.css("paddingRight") || 0, 10)))
                }
            }), t.placeholder = e(r.placeholder.element.call(t.element, t.currentItem)), t.currentItem.after(t.placeholder), r.placeholder.update(t, t.placeholder)
        },
        _contactContainers: function (t) {
            var n, r, i, s, o, u, a, f, l, c = null,
                h = null;
            for (n = this.containers.length - 1; n >= 0; n--)
                if (!e.contains(this.currentItem[0], this.containers[n].element[0]))
                    if (this._intersectsWith(this.containers[n].containerCache)) {
                        if (c && e.contains(this.containers[n].element[0], c.element[0])) continue;
                        c = this.containers[n], h = n
                    } else this.containers[n].containerCache.over && (this.containers[n]._trigger("out", t, this._uiHash(this)), this.containers[n].containerCache.over = 0);
            if (c)
                if (1 === this.containers.length) this.containers[h]._trigger("over", t, this._uiHash(this)), this.containers[h].containerCache.over = 1;
                else {
                    for (i = 1e4, s = null, o = this.containers[h].floating ? "left" : "top", u = this.containers[h].floating ? "width" : "height", a = this.positionAbs[o] + this.offset.click[o], r = this.items.length - 1; r >= 0; r--) e.contains(this.containers[h].element[0], this.items[r].item[0]) && this.items[r].item[0] !== this.currentItem[0] && (f = this.items[r].item.offset()[o], l = !1, Math.abs(f - a) > Math.abs(f + this.items[r][u] - a) && (l = !0, f += this.items[r][u]), Math.abs(f - a) < i && (i = Math.abs(f - a), s = this.items[r], this.direction = l ? "up" : "down"));
                    if (!s && !this.options.dropOnEmpty) return;
                    this.currentContainer = this.containers[h], s ? this._rearrange(t, s, null, !0) : this._rearrange(t, null, this.containers[h].element, !0), this._trigger("change", t, this._uiHash()), this.containers[h]._trigger("change", t, this._uiHash(this)), this.options.placeholder.update(this.currentContainer, this.placeholder), this.containers[h]._trigger("over", t, this._uiHash(this)), this.containers[h].containerCache.over = 1
                }
        },
        _createHelper: function (t) {
            var n = this.options,
                r = e.isFunction(n.helper) ? e(n.helper.apply(this.element[0], [t, this.currentItem])) : "clone" === n.helper ? this.currentItem.clone() : this.currentItem;
            return r.parents("body").length || e("parent" !== n.appendTo ? n.appendTo : this.currentItem[0].parentNode)[0].appendChild(r[0]), r[0] === this.currentItem[0] && (this._storedCSS = {
                width: this.currentItem[0].style.width,
                height: this.currentItem[0].style.height,
                position: this.currentItem.css("position"),
                top: this.currentItem.css("top"),
                left: this.currentItem.css("left")
            }), (!r[0].style.width || n.forceHelperSize) && r.width(this.currentItem.width()), (!r[0].style.height || n.forceHelperSize) && r.height(this.currentItem.height()), r
        },
        _adjustOffsetFromHelper: function (t) {
            "string" == typeof t && (t = t.split(" ")), e.isArray(t) && (t = {
                left: +t[0],
                top: +t[1] || 0
            }), "left" in t && (this.offset.click.left = t.left + this.margins.left), "right" in t && (this.offset.click.left = this.helperProportions.width - t.right + this.margins.left), "top" in t && (this.offset.click.top = t.top + this.margins.top), "bottom" in t && (this.offset.click.top = this.helperProportions.height - t.bottom + this.margins.top)
        },
        _getParentOffset: function () {
            this.offsetParent = this.helper.offsetParent();
            var t = this.offsetParent.offset();
            return "absolute" === this.cssPosition && this.scrollParent[0] !== document && e.contains(this.scrollParent[0], this.offsetParent[0]) && (t.left += this.scrollParent.scrollLeft(), t.top += this.scrollParent.scrollTop()), (this.offsetParent[0] === document.body || this.offsetParent[0].tagName && "html" === this.offsetParent[0].tagName.toLowerCase() && e.ui.ie) && (t = {
                top: 0,
                left: 0
            }), {
                top: t.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
                left: t.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
            }
        },
        _getRelativeOffset: function () {
            if ("relative" === this.cssPosition) {
                var e = this.currentItem.position();
                return {
                    top: e.top - (parseInt(this.helper.css("top"), 10) || 0) + this.scrollParent.scrollTop(),
                    left: e.left - (parseInt(this.helper.css("left"), 10) || 0) + this.scrollParent.scrollLeft()
                }
            }
            return {
                top: 0,
                left: 0
            }
        },
        _cacheMargins: function () {
            this.margins = {
                left: parseInt(this.currentItem.css("marginLeft"), 10) || 0,
                top: parseInt(this.currentItem.css("marginTop"), 10) || 0
            }
        },
        _cacheHelperProportions: function () {
            this.helperProportions = {
                width: this.helper.outerWidth(),
                height: this.helper.outerHeight()
            }
        },
        _setContainment: function () {
            var t, n, r, i = this.options;
            "parent" === i.containment && (i.containment = this.helper[0].parentNode), ("document" === i.containment || "window" === i.containment) && (this.containment = [0 - this.offset.relative.left - this.offset.parent.left, 0 - this.offset.relative.top - this.offset.parent.top, e("document" === i.containment ? document : window).width() - this.helperProportions.width - this.margins.left, (e("document" === i.containment ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top]), /^(document|window|parent)$/.test(i.containment) || (t = e(i.containment)[0], n = e(i.containment).offset(), r = "hidden" !== e(t).css("overflow"), this.containment = [n.left + (parseInt(e(t).css("borderLeftWidth"), 10) || 0) + (parseInt(e(t).css("paddingLeft"), 10) || 0) - this.margins.left, n.top + (parseInt(e(t).css("borderTopWidth"), 10) || 0) + (parseInt(e(t).css("paddingTop"), 10) || 0) - this.margins.top, n.left + (r ? Math.max(t.scrollWidth, t.offsetWidth) : t.offsetWidth) - (parseInt(e(t).css("borderLeftWidth"), 10) || 0) - (parseInt(e(t).css("paddingRight"), 10) || 0) - this.helperProportions.width - this.margins.left, n.top + (r ? Math.max(t.scrollHeight, t.offsetHeight) : t.offsetHeight) - (parseInt(e(t).css("borderTopWidth"), 10) || 0) - (parseInt(e(t).css("paddingBottom"), 10) || 0) - this.helperProportions.height - this.margins.top])
        },
        _convertPositionTo: function (t, n) {
            n || (n = this.position);
            var r = "absolute" === t ? 1 : -1,
                i = "absolute" !== this.cssPosition || this.scrollParent[0] !== document && e.contains(this.scrollParent[0], this.offsetParent[0]) ? this.scrollParent : this.offsetParent,
                s = /(html|body)/i.test(i[0].tagName);
            return {
                top: n.top + this.offset.relative.top * r + this.offset.parent.top * r - ("fixed" === this.cssPosition ? -this.scrollParent.scrollTop() : s ? 0 : i.scrollTop()) * r,
                left: n.left + this.offset.relative.left * r + this.offset.parent.left * r - ("fixed" === this.cssPosition ? -this.scrollParent.scrollLeft() : s ? 0 : i.scrollLeft()) * r
            }
        },
        _generatePosition: function (t) {
            var n, r, i = this.options,
                s = t.pageX,
                o = t.pageY,
                u = "absolute" !== this.cssPosition || this.scrollParent[0] !== document && e.contains(this.scrollParent[0], this.offsetParent[0]) ? this.scrollParent : this.offsetParent,
                a = /(html|body)/i.test(u[0].tagName);
            return "relative" === this.cssPosition && (this.scrollParent[0] === document || this.scrollParent[0] === this.offsetParent[0]) && (this.offset.relative = this._getRelativeOffset()), this.originalPosition && (this.containment && (t.pageX - this.offset.click.left < this.containment[0] && (s = this.containment[0] + this.offset.click.left), t.pageY - this.offset.click.top < this.containment[1] && (o = this.containment[1] + this.offset.click.top), t.pageX - this.offset.click.left > this.containment[2] && (s = this.containment[2] + this.offset.click.left), t.pageY - this.offset.click.top > this.containment[3] && (o = this.containment[3] + this.offset.click.top)), i.grid && (n = this.originalPageY + Math.round((o - this.originalPageY) / i.grid[1]) * i.grid[1], o = this.containment ? n - this.offset.click.top >= this.containment[1] && n - this.offset.click.top <= this.containment[3] ? n : n - this.offset.click.top >= this.containment[1] ? n - i.grid[1] : n + i.grid[1] : n, r = this.originalPageX + Math.round((s - this.originalPageX) / i.grid[0]) * i.grid[0], s = this.containment ? r - this.offset.click.left >= this.containment[0] && r - this.offset.click.left <= this.containment[2] ? r : r - this.offset.click.left >= this.containment[0] ? r - i.grid[0] : r + i.grid[0] : r)), {
                top: o - this.offset.click.top - this.offset.relative.top - this.offset.parent.top + ("fixed" === this.cssPosition ? -this.scrollParent.scrollTop() : a ? 0 : u.scrollTop()),
                left: s - this.offset.click.left - this.offset.relative.left - this.offset.parent.left + ("fixed" === this.cssPosition ? -this.scrollParent.scrollLeft() : a ? 0 : u.scrollLeft())
            }
        },
        _rearrange: function (e, t, n, r) {
            n ? n[0].appendChild(this.placeholder[0]) : t.item[0].parentNode.insertBefore(this.placeholder[0], "down" === this.direction ? t.item[0] : t.item[0].nextSibling), this.counter = this.counter ? ++this.counter : 1;
            var i = this.counter;
            this._delay(function () {
                i === this.counter && this.refreshPositions(!r)
            })
        },
        _clear: function (t, n) {
            this.reverting = !1;
            var r, i = [];
            if (!this._noFinalSort && this.currentItem.parent().length && this.placeholder.before(this.currentItem), this._noFinalSort = null, this.helper[0] === this.currentItem[0]) {
                for (r in this._storedCSS)("auto" === this._storedCSS[r] || "static" === this._storedCSS[r]) && (this._storedCSS[r] = "");
                this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")
            } else this.currentItem.show();
            for (this.fromOutside && !n && i.push(function (e) {
                this._trigger("receive", e, this._uiHash(this.fromOutside))
            }), (this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !n && i.push(function (e) {
                this._trigger("update", e, this._uiHash())
            }), this !== this.currentContainer && (n || (i.push(function (e) {
                this._trigger("remove", e, this._uiHash())
            }), i.push(function (e) {
                return function (t) {
                    e._trigger("receive", t, this._uiHash(this))
                }
            }.call(this, this.currentContainer)), i.push(function (e) {
                return function (t) {
                    e._trigger("update", t, this._uiHash(this))
                }
            }.call(this, this.currentContainer)))), r = this.containers.length - 1; r >= 0; r--) n || i.push(function (e) {
                return function (t) {
                    e._trigger("deactivate", t, this._uiHash(this))
                }
            }.call(this, this.containers[r])), this.containers[r].containerCache.over && (i.push(function (e) {
                return function (t) {
                    e._trigger("out", t, this._uiHash(this))
                }
            }.call(this, this.containers[r])), this.containers[r].containerCache.over = 0);
            if (this._storedCursor && e("body").css("cursor", this._storedCursor), this._storedOpacity && this.helper.css("opacity", this._storedOpacity), this._storedZIndex && this.helper.css("zIndex", "auto" === this._storedZIndex ? "" : this._storedZIndex), this.dragging = !1, this.cancelHelperRemoval) {
                if (!n) {
                    for (this._trigger("beforeStop", t, this._uiHash()), r = 0; r < i.length; r++) i[r].call(this, t);
                    this._trigger("stop", t, this._uiHash())
                }
                return this.fromOutside = !1, !1
            }
            if (n || this._trigger("beforeStop", t, this._uiHash()), this.placeholder[0].parentNode.removeChild(this.placeholder[0]), this.helper[0] !== this.currentItem[0] && this.helper.remove(), this.helper = null, !n) {
                for (r = 0; r < i.length; r++) i[r].call(this, t);
                this._trigger("stop", t, this._uiHash())
            }
            return this.fromOutside = !1, !0
        },
        _trigger: function () {
            e.Widget.prototype._trigger.apply(this, arguments) === !1 && this.cancel()
        },
        _uiHash: function (t) {
            var n = t || this;
            return {
                helper: n.helper,
                placeholder: n.placeholder || e([]),
                position: n.position,
                originalPosition: n.originalPosition,
                offset: n.positionAbs,
                item: n.currentItem,
                sender: t ? t.element : null
            }
        }
    })
}(jQuery),
function (e) {
    function t(e) {
        return function () {
            var t = this.element.val();
            e.apply(this, arguments), this._refresh(), t !== this.element.val() && this._trigger("change")
        }
    }
    e.widget("ui.spinner", {
        version: "1.10.1",
        defaultElement: "<input>",
        widgetEventPrefix: "spin",
        options: {
            culture: null,
            icons: {
                down: "ui-icon-triangle-1-s",
                up: "ui-icon-triangle-1-n"
            },
            incremental: !0,
            max: null,
            min: null,
            numberFormat: null,
            page: 10,
            step: 1,
            change: null,
            spin: null,
            start: null,
            stop: null
        },
        _create: function () {
            this._setOption("max", this.options.max), this._setOption("min", this.options.min), this._setOption("step", this.options.step), this._value(this.element.val(), !0), this._draw(), this._on(this._events), this._refresh(), this._on(this.window, {
                beforeunload: function () {
                    this.element.removeAttr("autocomplete")
                }
            })
        },
        _getCreateOptions: function () {
            var t = {},
                n = this.element;
            return e.each(["min", "max", "step"], function (e, r) {
                var i = n.attr(r);
                void 0 !== i && i.length && (t[r] = i)
            }), t
        },
        _events: {
            keydown: function (e) {
                this._start(e) && this._keydown(e) && e.preventDefault()
            },
            keyup: "_stop",
            focus: function () {
                this.previous = this.element.val()
            },
            blur: function (e) {
                return this.cancelBlur ? (delete this.cancelBlur, void 0) : (this._refresh(), this.previous !== this.element.val() && this._trigger("change", e), void 0)
            },
            mousewheel: function (e, t) {
                return t ? this.spinning || this._start(e) ? (this._spin((t > 0 ? 1 : -1) * this.options.step, e), clearTimeout(this.mousewheelTimer), this.mousewheelTimer = this._delay(function () {
                    this.spinning && this._stop(e)
                }, 100), e.preventDefault(), void 0) : !1 : void 0
            },
            "mousedown .ui-spinner-button": function (t) {
                function r() {
                    var e = this.element[0] === this.document[0].activeElement;
                    e || (this.element.focus(), this.previous = n, this._delay(function () {
                        this.previous = n
                    }))
                }
                var n;
                n = this.element[0] === this.document[0].activeElement ? this.previous : this.element.val(), t.preventDefault(), r.call(this), this.cancelBlur = !0, this._delay(function () {
                    delete this.cancelBlur, r.call(this)
                }), this._start(t) !== !1 && this._repeat(null, e(t.currentTarget).hasClass("ui-spinner-up") ? 1 : -1, t)
            },
            "mouseup .ui-spinner-button": "_stop",
            "mouseenter .ui-spinner-button": function (t) {
                return e(t.currentTarget).hasClass("ui-state-active") ? this._start(t) === !1 ? !1 : (this._repeat(null, e(t.currentTarget).hasClass("ui-spinner-up") ? 1 : -1, t), void 0) : void 0
            },
            "mouseleave .ui-spinner-button": "_stop"
        },
        _draw: function () {
            var e = this.uiSpinner = this.element.addClass("ui-spinner-input").attr("autocomplete", "off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());
            this.element.attr("role", "spinbutton"), this.buttons = e.find(".ui-spinner-button").attr("tabIndex", -1).button().removeClass("ui-corner-all"), this.buttons.height() > Math.ceil(.5 * e.height()) && e.height() > 0 && e.height(e.height()), this.options.disabled && this.disable()
        },
        _keydown: function (t) {
            var n = this.options,
                r = e.ui.keyCode;
            switch (t.keyCode) {
            case r.UP:
                return this._repeat(null, 1, t), !0;
            case r.DOWN:
                return this._repeat(null, -1, t), !0;
            case r.PAGE_UP:
                return this._repeat(null, n.page, t), !0;
            case r.PAGE_DOWN:
                return this._repeat(null, -n.page, t), !0
            }
            return !1
        },
        _uiSpinnerHtml: function () {
            return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"
        },
        _buttonHtml: function () {
            return "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon " + this.options.icons.up + "'>&#9650;</span></a><a class='ui-spinner-button ui-spinner-down ui-corner-br'><span class='ui-icon " + this.options.icons.down + "'>&#9660;</span></a>"
        },
        _start: function (e) {
            return this.spinning || this._trigger("start", e) !== !1 ? (this.counter || (this.counter = 1), this.spinning = !0, !0) : !1
        },
        _repeat: function (e, t, n) {
            e = e || 500, clearTimeout(this.timer), this.timer = this._delay(function () {
                this._repeat(40, t, n)
            }, e), this._spin(t * this.options.step, n)
        },
        _spin: function (e, t) {
            var n = this.value() || 0;
            this.counter || (this.counter = 1), n = this._adjustValue(n + e * this._increment(this.counter)), this.spinning && this._trigger("spin", t, {
                value: n
            }) === !1 || (this._value(n), this.counter++)
        },
        _increment: function (t) {
            var n = this.options.incremental;
            return n ? e.isFunction(n) ? n(t) : Math.floor(t * t * t / 5e4 - t * t / 500 + 17 * t / 200 + 1) : 1
        },
        _precision: function () {
            var e = this._precisionOf(this.options.step);
            return null !== this.options.min && (e = Math.max(e, this._precisionOf(this.options.min))), e
        },
        _precisionOf: function (e) {
            var t = e.toString(),
                n = t.indexOf(".");
            return -1 === n ? 0 : t.length - n - 1
        },
        _adjustValue: function (e) {
            var t, n, r = this.options;
            return t = null !== r.min ? r.min : 0, n = e - t, n = Math.round(n / r.step) * r.step, e = t + n, e = parseFloat(e.toFixed(this._precision())), null !== r.max && e > r.max ? r.max : null !== r.min && e < r.min ? r.min : e
        },
        _stop: function (e) {
            this.spinning && (clearTimeout(this.timer), clearTimeout(this.mousewheelTimer), this.counter = 0, this.spinning = !1, this._trigger("stop", e))
        },
        _setOption: function (e, t) {
            if ("culture" === e || "numberFormat" === e) {
                var n = this._parse(this.element.val());
                return this.options[e] = t, this.element.val(this._format(n)), void 0
            }("max" === e || "min" === e || "step" === e) && "string" == typeof t && (t = this._parse(t)), "icons" === e && (this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(t.up), this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(t.down)), this._super(e, t), "disabled" === e && (t ? (this.element.prop("disabled", !0), this.buttons.button("disable")) : (this.element.prop("disabled", !1), this.buttons.button("enable")))
        },
        _setOptions: t(function (e) {
            this._super(e), this._value(this.element.val())
        }),
        _parse: function (e) {
            return "string" == typeof e && "" !== e && (e = window.Globalize && this.options.numberFormat ? Globalize.parseFloat(e, 10, this.options.culture) : +e), "" === e || isNaN(e) ? null : e
        },
        _format: function (e) {
            return "" === e ? "" : window.Globalize && this.options.numberFormat ? Globalize.format(e, this.options.numberFormat, this.options.culture) : e
        },
        _refresh: function () {
            this.element.attr({
                "aria-valuemin": this.options.min,
                "aria-valuemax": this.options.max,
                "aria-valuenow": this._parse(this.element.val())
            })
        },
        _value: function (e, t) {
            var n;
            "" !== e && (n = this._parse(e), null !== n && (t || (n = this._adjustValue(n)), e = this._format(n))), this.element.val(e), this._refresh()
        },
        _destroy: function () {
            this.element.removeClass("ui-spinner-input").prop("disabled", !1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"), this.uiSpinner.replaceWith(this.element)
        },
        stepUp: t(function (e) {
            this._stepUp(e)
        }),
        _stepUp: function (e) {
            this._start() && (this._spin((e || 1) * this.options.step), this._stop())
        },
        stepDown: t(function (e) {
            this._stepDown(e)
        }),
        _stepDown: function (e) {
            this._start() && (this._spin((e || 1) * -this.options.step), this._stop())
        },
        pageUp: t(function (e) {
            this._stepUp((e || 1) * this.options.page)
        }),
        pageDown: t(function (e) {
            this._stepDown((e || 1) * this.options.page)
        }),
        value: function (e) {
            return arguments.length ? (t(this._value).call(this, e), void 0) : this._parse(this.element.val())
        },
        widget: function () {
            return this.uiSpinner
        }
    })
}(jQuery),
function (e, t) {
    function i() {
        return ++n
    }

    function s(e) {
        return e.hash.length > 1 && decodeURIComponent(e.href.replace(r, "")) === decodeURIComponent(location.href.replace(r, ""))
    }
    var n = 0,
        r = /#.*$/;
    e.widget("ui.tabs", {
        version: "1.10.1",
        delay: 300,
        options: {
            active: null,
            collapsible: !1,
            event: "click",
            heightStyle: "content",
            hide: null,
            show: null,
            activate: null,
            beforeActivate: null,
            beforeLoad: null,
            load: null
        },
        _create: function () {
            var t = this,
                n = this.options;
            this.running = !1, this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible", n.collapsible).delegate(".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function (t) {
                e(this).is(".ui-state-disabled") && t.preventDefault()
            }).delegate(".ui-tabs-anchor", "focus" + this.eventNamespace, function () {
                e(this).closest("li").is(".ui-state-disabled") && this.blur()
            }), this._processTabs(), n.active = this._initialActive(), e.isArray(n.disabled) && (n.disabled = e.unique(n.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"), function (e) {
                return t.tabs.index(e)
            }))).sort()), this.active = this.options.active !== !1 && this.anchors.length ? this._findActive(n.active) : e(), this._refresh(), this.active.length && this.load(n.active)
        },
        _initialActive: function () {
            var t = this.options.active,
                n = this.options.collapsible,
                r = location.hash.substring(1);
            return null === t && (r && this.tabs.each(function (n, i) {
                return e(i).attr("aria-controls") === r ? (t = n, !1) : void 0
            }), null === t && (t = this.tabs.index(this.tabs.filter(".ui-tabs-active"))), (null === t || -1 === t) && (t = this.tabs.length ? 0 : !1)), t !== !1 && (t = this.tabs.index(this.tabs.eq(t)), -1 === t && (t = n ? !1 : 0)), !n && t === !1 && this.anchors.length && (t = 0), t
        },
        _getCreateEventData: function () {
            return {
                tab: this.active,
                panel: this.active.length ? this._getPanelForTab(this.active) : e()
            }
        },
        _tabKeydown: function (t) {
            var n = e(this.document[0].activeElement).closest("li"),
                r = this.tabs.index(n),
                i = !0;
            if (!this._handlePageNav(t)) {
                switch (t.keyCode) {
                case e.ui.keyCode.RIGHT:
                case e.ui.keyCode.DOWN:
                    r++;
                    break;
                case e.ui.keyCode.UP:
                case e.ui.keyCode.LEFT:
                    i = !1, r--;
                    break;
                case e.ui.keyCode.END:
                    r = this.anchors.length - 1;
                    break;
                case e.ui.keyCode.HOME:
                    r = 0;
                    break;
                case e.ui.keyCode.SPACE:
                    return t.preventDefault(), clearTimeout(this.activating), this._activate(r), void 0;
                case e.ui.keyCode.ENTER:
                    return t.preventDefault(), clearTimeout(this.activating), this._activate(r === this.options.active ? !1 : r), void 0;
                default:
                    return
                }
                t.preventDefault(), clearTimeout(this.activating), r = this._focusNextTab(r, i), t.ctrlKey || (n.attr("aria-selected", "false"), this.tabs.eq(r).attr("aria-selected", "true"), this.activating = this._delay(function () {
                    this.option("active", r)
                }, this.delay))
            }
        },
        _panelKeydown: function (t) {
            this._handlePageNav(t) || t.ctrlKey && t.keyCode === e.ui.keyCode.UP && (t.preventDefault(), this.active.focus())
        },
        _handlePageNav: function (t) {
            return t.altKey && t.keyCode === e.ui.keyCode.PAGE_UP ? (this._activate(this._focusNextTab(this.options.active - 1, !1)), !0) : t.altKey && t.keyCode === e.ui.keyCode.PAGE_DOWN ? (this._activate(this._focusNextTab(this.options.active + 1, !0)), !0) : void 0
        },
        _findNextTab: function (t, n) {
            function i() {
                return t > r && (t = 0), 0 > t && (t = r), t
            }
            for (var r = this.tabs.length - 1; - 1 !== e.inArray(i(), this.options.disabled);) t = n ? t + 1 : t - 1;
            return t
        },
        _focusNextTab: function (e, t) {
            return e = this._findNextTab(e, t), this.tabs.eq(e).focus(), e
        },
        _setOption: function (e, t) {
            return "active" === e ? (this._activate(t), void 0) : "disabled" === e ? (this._setupDisabled(t), void 0) : (this._super(e, t), "collapsible" === e && (this.element.toggleClass("ui-tabs-collapsible", t), !t && this.options.active === !1 && this._activate(0)), "event" === e && this._setupEvents(t), "heightStyle" === e && this._setupHeightStyle(t), void 0)
        },
        _tabId: function (e) {
            return e.attr("aria-controls") || "ui-tabs-" + i()
        },
        _sanitizeSelector: function (e) {
            return e ? e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&") : ""
        },
        refresh: function () {
            var t = this.options,
                n = this.tablist.children(":has(a[href])");
            t.disabled = e.map(n.filter(".ui-state-disabled"), function (e) {
                return n.index(e)
            }), this._processTabs(), t.active !== !1 && this.anchors.length ? this.active.length && !e.contains(this.tablist[0], this.active[0]) ? this.tabs.length === t.disabled.length ? (t.active = !1, this.active = e()) : this._activate(this._findNextTab(Math.max(0, t.active - 1), !1)) : t.active = this.tabs.index(this.active) : (t.active = !1, this.active = e()), this._refresh()
        },
        _refresh: function () {
            this._setupDisabled(this.options.disabled), this._setupEvents(this.options.event), this._setupHeightStyle(this.options.heightStyle), this.tabs.not(this.active).attr({
                "aria-selected": "false",
                tabIndex: -1
            }), this.panels.not(this._getPanelForTab(this.active)).hide().attr({
                "aria-expanded": "false",
                "aria-hidden": "true"
            }), this.active.length ? (this.active.addClass("ui-tabs-active ui-state-active").attr({
                "aria-selected": "true",
                tabIndex: 0
            }), this._getPanelForTab(this.active).show().attr({
                "aria-expanded": "true",
                "aria-hidden": "false"
            })) : this.tabs.eq(0).attr("tabIndex", 0)
        },
        _processTabs: function () {
            var t = this;
            this.tablist = this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role", "tablist"), this.tabs = this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({
                role: "tab",
                tabIndex: -1
            }), this.anchors = this.tabs.map(function () {
                return e("a", this)[0]
            }).addClass("ui-tabs-anchor").attr({
                role: "presentation",
                tabIndex: -1
            }), this.panels = e(), this.anchors.each(function (n, r) {
                var i, o, u, a = e(r).uniqueId().attr("id"),
                    f = e(r).closest("li"),
                    l = f.attr("aria-controls");
                s(r) ? (i = r.hash, o = t.element.find(t._sanitizeSelector(i))) : (u = t._tabId(f), i = "#" + u, o = t.element.find(i), o.length || (o = t._createPanel(u), o.insertAfter(t.panels[n - 1] || t.tablist)), o.attr("aria-live", "polite")), o.length && (t.panels = t.panels.add(o)), l && f.data("ui-tabs-aria-controls", l), f.attr({
                    "aria-controls": i.substring(1),
                    "aria-labelledby": a
                }), o.attr("aria-labelledby", a)
            }), this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role", "tabpanel")
        },
        _getList: function () {
            return this.element.find("ol,ul").eq(0)
        },
        _createPanel: function (t) {
            return e("<div>").attr("id", t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy", !0)
        },
        _setupDisabled: function (t) {
            e.isArray(t) && (t.length ? t.length === this.anchors.length && (t = !0) : t = !1);
            for (var r, n = 0; r = this.tabs[n]; n++) t === !0 || -1 !== e.inArray(n, t) ? e(r).addClass("ui-state-disabled").attr("aria-disabled", "true") : e(r).removeClass("ui-state-disabled").removeAttr("aria-disabled");
            this.options.disabled = t
        },
        _setupEvents: function (t) {
            var n = {
                click: function (e) {
                    e.preventDefault()
                }
            };
            t && e.each(t.split(" "), function (e, t) {
                n[t] = "_eventHandler"
            }), this._off(this.anchors.add(this.tabs).add(this.panels)), this._on(this.anchors, n), this._on(this.tabs, {
                keydown: "_tabKeydown"
            }), this._on(this.panels, {
                keydown: "_panelKeydown"
            }), this._focusable(this.tabs), this._hoverable(this.tabs)
        },
        _setupHeightStyle: function (t) {
            var n, r = this.element.parent();
            "fill" === t ? (n = r.height(), n -= this.element.outerHeight() - this.element.height(), this.element.siblings(":visible").each(function () {
                var t = e(this),
                    r = t.css("position");
                "absolute" !== r && "fixed" !== r && (n -= t.outerHeight(!0))
            }), this.element.children().not(this.panels).each(function () {
                n -= e(this).outerHeight(!0)
            }), this.panels.each(function () {
                e(this).height(Math.max(0, n - e(this).innerHeight() + e(this).height()))
            }).css("overflow", "auto")) : "auto" === t && (n = 0, this.panels.each(function () {
                n = Math.max(n, e(this).height("").height())
            }).height(n))
        },
        _eventHandler: function (t) {
            var n = this.options,
                r = this.active,
                i = e(t.currentTarget),
                s = i.closest("li"),
                o = s[0] === r[0],
                u = o && n.collapsible,
                a = u ? e() : this._getPanelForTab(s),
                f = r.length ? this._getPanelForTab(r) : e(),
                l = {
                    oldTab: r,
                    oldPanel: f,
                    newTab: u ? e() : s,
                    newPanel: a
                };
            t.preventDefault(), s.hasClass("ui-state-disabled") || s.hasClass("ui-tabs-loading") || this.running || o && !n.collapsible || this._trigger("beforeActivate", t, l) === !1 || (n.active = u ? !1 : this.tabs.index(s), this.active = o ? e() : s, this.xhr && this.xhr.abort(), !f.length && !a.length && e.error("jQuery UI Tabs: Mismatching fragment identifier."), a.length && this.load(this.tabs.index(s), t), this._toggle(t, l))
        },
        _toggle: function (t, n) {
            function o() {
                r.running = !1, r._trigger("activate", t, n)
            }

            function u() {
                n.newTab.closest("li").addClass("ui-tabs-active ui-state-active"), i.length && r.options.show ? r._show(i, r.options.show, o) : (i.show(), o())
            }
            var r = this,
                i = n.newPanel,
                s = n.oldPanel;
            this.running = !0, s.length && this.options.hide ? this._hide(s, this.options.hide, function () {
                n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"), u()
            }) : (n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"), s.hide(), u()), s.attr({
                "aria-expanded": "false",
                "aria-hidden": "true"
            }), n.oldTab.attr("aria-selected", "false"), i.length && s.length ? n.oldTab.attr("tabIndex", -1) : i.length && this.tabs.filter(function () {
                return 0 === e(this).attr("tabIndex")
            }).attr("tabIndex", -1), i.attr({
                "aria-expanded": "true",
                "aria-hidden": "false"
            }), n.newTab.attr({
                "aria-selected": "true",
                tabIndex: 0
            })
        },
        _activate: function (t) {
            var n, r = this._findActive(t);
            r[0] !== this.active[0] && (r.length || (r = this.active), n = r.find(".ui-tabs-anchor")[0], this._eventHandler({
                target: n,
                currentTarget: n,
                preventDefault: e.noop
            }))
        },
        _findActive: function (t) {
            return t === !1 ? e() : this.tabs.eq(t)
        },
        _getIndex: function (e) {
            return "string" == typeof e && (e = this.anchors.index(this.anchors.filter("[href$='" + e + "']"))), e
        },
        _destroy: function () {
            this.xhr && this.xhr.abort(), this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"), this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"), this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(), this.tabs.add(this.panels).each(function () {
                e.data(this, "ui-tabs-destroy") ? e(this).remove() : e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")
            }), this.tabs.each(function () {
                var t = e(this),
                    n = t.data("ui-tabs-aria-controls");
                n ? t.attr("aria-controls", n).removeData("ui-tabs-aria-controls") : t.removeAttr("aria-controls")
            }), this.panels.show(), "content" !== this.options.heightStyle && this.panels.css("height", "")
        },
        enable: function (n) {
            var r = this.options.disabled;
            r !== !1 && (n === t ? r = !1 : (n = this._getIndex(n), r = e.isArray(r) ? e.map(r, function (e) {
                return e !== n ? e : null
            }) : e.map(this.tabs, function (e, t) {
                return t !== n ? t : null
            })), this._setupDisabled(r))
        },
        disable: function (n) {
            var r = this.options.disabled;
            if (r !== !0) {
                if (n === t) r = !0;
                else {
                    if (n = this._getIndex(n), -1 !== e.inArray(n, r)) return;
                    r = e.isArray(r) ? e.merge([n], r).sort() : [n]
                }
                this._setupDisabled(r)
            }
        },
        load: function (t, n) {
            t = this._getIndex(t);
            var r = this,
                i = this.tabs.eq(t),
                o = i.find(".ui-tabs-anchor"),
                u = this._getPanelForTab(i),
                a = {
                    tab: i,
                    panel: u
                };
            s(o[0]) || (this.xhr = e.ajax(this._ajaxSettings(o, n, a)), this.xhr && "canceled" !== this.xhr.statusText && (i.addClass("ui-tabs-loading"), u.attr("aria-busy", "true"), this.xhr.success(function (e) {
                setTimeout(function () {
                    u.html(e), r._trigger("load", n, a)
                }, 1)
            }).complete(function (e, t) {
                setTimeout(function () {
                    "abort" === t && r.panels.stop(!1, !0), i.removeClass("ui-tabs-loading"), u.removeAttr("aria-busy"), e === r.xhr && delete r.xhr
                }, 1)
            })))
        },
        _ajaxSettings: function (t, n, r) {
            var i = this;
            return {
                url: t.attr("href"),
                beforeSend: function (t, s) {
                    return i._trigger("beforeLoad", n, e.extend({
                        jqXHR: t,
                        ajaxSettings: s
                    }, r))
                }
            }
        },
        _getPanelForTab: function (t) {
            var n = e(t).attr("aria-controls");
            return this.element.find(this._sanitizeSelector("#" + n))
        }
    })
}(jQuery),
function (e) {
    function n(t, n) {
        var r = (t.attr("aria-describedby") || "").split(/\s+/);
        r.push(n), t.data("ui-tooltip-id", n).attr("aria-describedby", e.trim(r.join(" ")))
    }

    function r(t) {
        var n = t.data("ui-tooltip-id"),
            r = (t.attr("aria-describedby") || "").split(/\s+/),
            i = e.inArray(n, r); - 1 !== i && r.splice(i, 1), t.removeData("ui-tooltip-id"), r = e.trim(r.join(" ")), r ? t.attr("aria-describedby", r) : t.removeAttr("aria-describedby")
    }
    var t = 0;
    e.widget("ui.tooltip", {
        version: "1.10.1",
        options: {
            content: function () {
                var t = e(this).attr("title") || "";
                return e("<a>").text(t).html()
            },
            hide: !0,
            items: "[title]:not([disabled])",
            position: {
                my: "left top+15",
                at: "left bottom",
                collision: "flipfit flip"
            },
            show: !0,
            tooltipClass: null,
            track: !1,
            close: null,
            open: null
        },
        _create: function () {
            this._on({
                mouseover: "open",
                focusin: "open"
            }), this.tooltips = {}, this.parents = {}, this.options.disabled && this._disable()
        },
        _setOption: function (t, n) {
            var r = this;
            return "disabled" === t ? (this[n ? "_disable" : "_enable"](), this.options[t] = n, void 0) : (this._super(t, n), "content" === t && e.each(this.tooltips, function (e, t) {
                r._updateContent(t)
            }), void 0)
        },
        _disable: function () {
            var t = this;
            e.each(this.tooltips, function (n, r) {
                var i = e.Event("blur");
                i.target = i.currentTarget = r[0], t.close(i, !0)
            }), this.element.find(this.options.items).addBack().each(function () {
                var t = e(this);
                t.is("[title]") && t.data("ui-tooltip-title", t.attr("title")).attr("title", "")
            })
        },
        _enable: function () {
            this.element.find(this.options.items).addBack().each(function () {
                var t = e(this);
                t.data("ui-tooltip-title") && t.attr("title", t.data("ui-tooltip-title"))
            })
        },
        open: function (t) {
            var n = this,
                r = e(t ? t.target : this.element).closest(this.options.items);
            r.length && !r.data("ui-tooltip-id") && (r.attr("title") && r.data("ui-tooltip-title", r.attr("title")), r.data("ui-tooltip-open", !0), t && "mouseover" === t.type && r.parents().each(function () {
                var r, t = e(this);
                t.data("ui-tooltip-open") && (r = e.Event("blur"), r.target = r.currentTarget = this, n.close(r, !0)), t.attr("title") && (t.uniqueId(), n.parents[this.id] = {
                    element: this,
                    title: t.attr("title")
                }, t.attr("title", ""))
            }), this._updateContent(r, t))
        },
        _updateContent: function (e, t) {
            var n, r = this.options.content,
                i = this,
                s = t ? t.type : null;
            return "string" == typeof r ? this._open(t, e, r) : (n = r.call(e[0], function (n) {
                e.data("ui-tooltip-open") && i._delay(function () {
                    t && (t.type = s), this._open(t, e, n)
                })
            }), n && this._open(t, e, n), void 0)
        },
        _open: function (t, r, i) {
            function f(e) {
                a.of = e, s.is(":hidden") || s.position(a)
            }
            var s, o, u, a = e.extend({}, this.options.position);
            if (i) {
                if (s = this._find(r), s.length) return s.find(".ui-tooltip-content").html(i), void 0;
                r.is("[title]") && (t && "mouseover" === t.type ? r.attr("title", "") : r.removeAttr("title")), s = this._tooltip(r), n(r, s.attr("id")), s.find(".ui-tooltip-content").html(i), this.options.track && t && /^mouse/.test(t.type) ? (this._on(this.document, {
                    mousemove: f
                }), f(t)) : s.position(e.extend({
                    of: r
                }, this.options.position)), s.hide(), this._show(s, this.options.show), this.options.show && this.options.show.delay && (u = this.delayedShow = setInterval(function () {
                    s.is(":visible") && (f(a.of), clearInterval(u))
                }, e.fx.interval)), this._trigger("open", t, {
                    tooltip: s
                }), o = {
                    keyup: function (t) {
                        if (t.keyCode === e.ui.keyCode.ESCAPE) {
                            var n = e.Event(t);
                            n.currentTarget = r[0], this.close(n, !0)
                        }
                    },
                    remove: function () {
                        this._removeTooltip(s)
                    }
                }, t && "mouseover" !== t.type || (o.mouseleave = "close"), t && "focusin" !== t.type || (o.focusout = "close"), this._on(!0, r, o)
            }
        },
        close: function (t) {
            var n = this,
                i = e(t ? t.currentTarget : this.element),
                s = this._find(i);
            this.closing || (clearInterval(this.delayedShow), i.data("ui-tooltip-title") && i.attr("title", i.data("ui-tooltip-title")), r(i), s.stop(!0), this._hide(s, this.options.hide, function () {
                n._removeTooltip(e(this))
            }), i.removeData("ui-tooltip-open"), this._off(i, "mouseleave focusout keyup"), i[0] !== this.element[0] && this._off(i, "remove"), this._off(this.document, "mousemove"), t && "mouseleave" === t.type && e.each(this.parents, function (t, r) {
                e(r.element).attr("title", r.title), delete n.parents[t]
            }), this.closing = !0, this._trigger("close", t, {
                tooltip: s
            }), this.closing = !1)
        },
        _tooltip: function (n) {
            var r = "ui-tooltip-" + t++,
                i = e("<div>").attr({
                    id: r,
                    role: "tooltip"
                }).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content " + (this.options.tooltipClass || ""));
            return e("<div>").addClass("ui-tooltip-content").appendTo(i), i.appendTo(this.document[0].body), this.tooltips[r] = n, i
        },
        _find: function (t) {
            var n = t.data("ui-tooltip-id");
            return n ? e("#" + n) : e()
        },
        _removeTooltip: function (e) {
            e.remove(), delete this.tooltips[e.attr("id")]
        },
        _destroy: function () {
            var t = this;
            e.each(this.tooltips, function (n, r) {
                var i = e.Event("blur");
                i.target = i.currentTarget = r[0], t.close(i, !0), e("#" + n).remove(), r.data("ui-tooltip-title") && (r.attr("title", r.data("ui-tooltip-title")), r.removeData("ui-tooltip-title"))
            })
        }
    })
}(jQuery),
function (e, t, n) {
    "function" == typeof define && define.amd ? define(["jquery"], function (r) {
        return n(r, e, t), r.mobile
    }) : n(e.jQuery, e, t)
}(this, document, function (e, t, n) {
    ! function (e, t, r) {
        "$:nomunge";

        function l(e) {
            return e = e || location.href, "#" + e.replace(/^[^#]*#?(.*)$/, "$1")
        }
        var o, i = "hashchange",
            s = n,
            u = e.event.special,
            a = s.documentMode,
            f = "on" + i in t && (a === r || a > 7);
        e.fn[i] = function (e) {
            return e ? this.bind(i, e) : this.trigger(i)
        }, e.fn[i].delay = 50, u[i] = e.extend(u[i], {
            setup: function () {
                return f ? !1 : (e(o.start), void 0)
            },
            teardown: function () {
                return f ? !1 : (e(o.stop), void 0)
            }
        }), o = function () {
            function p() {
                var n = l(),
                    r = h(u);
                n !== u ? (c(u = n, r), e(t).trigger(i)) : r !== u && (location.href = location.href.replace(/#.*/, "") + r), o = setTimeout(p, e.fn[i].delay)
            }
            var o, n = {},
                u = l(),
                a = function (e) {
                    return e
                },
                c = a,
                h = a;
            return n.start = function () {
                o || p()
            }, n.stop = function () {
                o && clearTimeout(o), o = r
            }, t.attachEvent && !t.addEventListener && !f && function () {
                var t, r;
                n.start = function () {
                    t || (r = e.fn[i].src, r = r && r + l(), t = e('<iframe tabindex="-1" title="empty"/>').hide().one("load", function () {
                        r || c(l()), p()
                    }).attr("src", r || "javascript:0").insertAfter("body")[0].contentWindow, s.onpropertychange = function () {
                        try {
                            "title" === event.propertyName && (t.document.title = s.title)
                        } catch (e) {}
                    })
                }, n.stop = a, h = function () {
                    return l(t.location.href)
                }, c = function (n, r) {
                    var o = t.document,
                        u = e.fn[i].domain;
                    n !== r && (o.title = s.title, o.open(), u && o.write('<script>document.domain="' + u + '"</script>'), o.close(), t.location.hash = n)
                }
            }(), n
        }()
    }(e, this),
    function (e) {
        e.mobile = {}
    }(e),
    function (e) {
        e.extend(e.mobile, {
            version: "1.4.2",
            subPageUrlKey: "ui-page",
            hideUrlBar: !0,
            keepNative: ":jqmData(role='none'), :jqmData(role='nojs')",
            activePageClass: "ui-page-active",
            activeBtnClass: "ui-btn-active",
            focusClass: "ui-focus",
            ajaxEnabled: !0,
            hashListeningEnabled: !0,
            linkBindingEnabled: !0,
            defaultPageTransition: "fade",
            maxTransitionWidth: !1,
            minScrollBack: 0,
            defaultDialogTransition: "pop",
            pageLoadErrorMessage: "Error Loading Page",
            pageLoadErrorMessageTheme: "a",
            phonegapNavigationEnabled: !1,
            autoInitializePage: !0,
            pushStateEnabled: !0,
            ignoreContentEnabled: !1,
            buttonMarkup: {
                hoverDelay: 200
            },
            dynamicBaseEnabled: !0,
            pageContainer: e(),
            allowCrossDomainPages: !1,
            dialogHashKey: "&ui-state=dialog"
        })
    }(e, this),
    function (e, t, n) {
        var r = {},
            i = e.find,
            s = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
            o = /:jqmData\(([^)]*)\)/g;
        e.extend(e.mobile, {
            ns: "",
            getAttribute: function (t, n) {
                var r;
                t = t.jquery ? t[0] : t, t && t.getAttribute && (r = t.getAttribute("data-" + e.mobile.ns + n));
                try {
                    r = "true" === r ? !0 : "false" === r ? !1 : "null" === r ? null : +r + "" === r ? +r : s.test(r) ? JSON.parse(r) : r
                } catch (i) {}
                return r
            },
            nsNormalizeDict: r,
            nsNormalize: function (t) {
                return r[t] || (r[t] = e.camelCase(e.mobile.ns + t))
            },
            closestPageData: function (e) {
                return e.closest(":jqmData(role='page'), :jqmData(role='dialog')").data("mobile-page")
            }
        }), e.fn.jqmData = function (t, r) {
            var i;
            return "undefined" != typeof t && (t && (t = e.mobile.nsNormalize(t)), i = arguments.length < 2 || r === n ? this.data(t) : this.data(t, r)), i
        }, e.jqmData = function (t, n, r) {
            var i;
            return "undefined" != typeof n && (i = e.data(t, n ? e.mobile.nsNormalize(n) : n, r)), i
        }, e.fn.jqmRemoveData = function (t) {
            return this.removeData(e.mobile.nsNormalize(t))
        }, e.jqmRemoveData = function (t, n) {
            return e.removeData(t, e.mobile.nsNormalize(n))
        }, e.find = function (t, n, r, s) {
            return t.indexOf(":jqmData") > -1 && (t = t.replace(o, "[data-" + (e.mobile.ns || "") + "$1]")), i.call(this, t, n, r, s)
        }, e.extend(e.find, i)
    }(e, this),
    function (e, t) {
        function s(t, n) {
            var r, i, s, u = t.nodeName.toLowerCase();
            return "area" === u ? (r = t.parentNode, i = r.name, t.href && i && "map" === r.nodeName.toLowerCase() ? (s = e("img[usemap=#" + i + "]")[0], !!s && o(s)) : !1) : (/input|select|textarea|button|object/.test(u) ? !t.disabled : "a" === u ? t.href || n : n) && o(t)
        }

        function o(t) {
            return e.expr.filters.visible(t) && !e(t).parents().addBack().filter(function () {
                return "hidden" === e.css(this, "visibility")
            }).length
        }
        var r = 0,
            i = /^ui-id-\d+$/;
        e.ui = e.ui || {}, e.extend(e.ui, {
            version: "c0ab71056b936627e8a7821f03c044aec6280a40",
            keyCode: {
                BACKSPACE: 8,
                COMMA: 188,
                DELETE: 46,
                DOWN: 40,
                END: 35,
                ENTER: 13,
                ESCAPE: 27,
                HOME: 36,
                LEFT: 37,
                PAGE_DOWN: 34,
                PAGE_UP: 33,
                PERIOD: 190,
                RIGHT: 39,
                SPACE: 32,
                TAB: 9,
                UP: 38
            }
        }), e.fn.extend({
            focus: function (t) {
                return function (n, r) {
                    return "number" == typeof n ? this.each(function () {
                        var t = this;
                        setTimeout(function () {
                            e(t).focus(), r && r.call(t)
                        }, n)
                    }) : t.apply(this, arguments)
                }
            }(e.fn.focus),
            scrollParent: function () {
                var t;
                return t = e.ui.ie && /(static|relative)/.test(this.css("position")) || /absolute/.test(this.css("position")) ? this.parents().filter(function () {
                    return /(relative|absolute|fixed)/.test(e.css(this, "position")) && /(auto|scroll)/.test(e.css(this, "overflow") + e.css(this, "overflow-y") + e.css(this, "overflow-x"))
                }).eq(0) : this.parents().filter(function () {
                    return /(auto|scroll)/.test(e.css(this, "overflow") + e.css(this, "overflow-y") + e.css(this, "overflow-x"))
                }).eq(0), /fixed/.test(this.css("position")) || !t.length ? e(this[0].ownerDocument || n) : t
            },
            uniqueId: function () {
                return this.each(function () {
                    this.id || (this.id = "ui-id-" + ++r)
                })
            },
            removeUniqueId: function () {
                return this.each(function () {
                    i.test(this.id) && e(this).removeAttr("id")
                })
            }
        }), e.extend(e.expr[":"], {
            data: e.expr.createPseudo ? e.expr.createPseudo(function (t) {
                return function (n) {
                    return !!e.data(n, t)
                }
            }) : function (t, n, r) {
                return !!e.data(t, r[3])
            },
            focusable: function (t) {
                return s(t, !isNaN(e.attr(t, "tabindex")))
            },
            tabbable: function (t) {
                var n = e.attr(t, "tabindex"),
                    r = isNaN(n);
                return (r || n >= 0) && s(t, !r)
            }
        }), e("<a>").outerWidth(1).jquery || e.each(["Width", "Height"], function (n, r) {
            function u(t, n, r, s) {
                return e.each(i, function () {
                    n -= parseFloat(e.css(t, "padding" + this)) || 0, r && (n -= parseFloat(e.css(t, "border" + this + "Width")) || 0), s && (n -= parseFloat(e.css(t, "margin" + this)) || 0)
                }), n
            }
            var i = "Width" === r ? ["Left", "Right"] : ["Top", "Bottom"],
                s = r.toLowerCase(),
                o = {
                    innerWidth: e.fn.innerWidth,
                    innerHeight: e.fn.innerHeight,
                    outerWidth: e.fn.outerWidth,
                    outerHeight: e.fn.outerHeight
                };
            e.fn["inner" + r] = function (n) {
                return n === t ? o["inner" + r].call(this) : this.each(function () {
                    e(this).css(s, u(this, n) + "px")
                })
            }, e.fn["outer" + r] = function (t, n) {
                return "number" != typeof t ? o["outer" + r].call(this, t) : this.each(function () {
                    e(this).css(s, u(this, t, !0, n) + "px")
                })
            }
        }), e.fn.addBack || (e.fn.addBack = function (e) {
            return this.add(null == e ? this.prevObject : this.prevObject.filter(e))
        }), e("<a>").data("a-b", "a").removeData("a-b").data("a-b") && (e.fn.removeData = function (t) {
            return function (n) {
                return arguments.length ? t.call(this, e.camelCase(n)) : t.call(this)
            }
        }(e.fn.removeData)), e.ui.ie = !!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()), e.support.selectstart = "onselectstart" in n.createElement("div"), e.fn.extend({
            disableSelection: function () {
                return this.bind((e.support.selectstart ? "selectstart" : "mousedown") + ".ui-disableSelection", function (e) {
                    e.preventDefault()
                })
            },
            enableSelection: function () {
                return this.unbind(".ui-disableSelection")
            },
            zIndex: function (r) {
                if (r !== t) return this.css("zIndex", r);
                if (this.length)
                    for (var s, o, i = e(this[0]); i.length && i[0] !== n;) {
                        if (s = i.css("position"), ("absolute" === s || "relative" === s || "fixed" === s) && (o = parseInt(i.css("zIndex"), 10), !isNaN(o) && 0 !== o)) return o;
                        i = i.parent()
                    }
                return 0
            }
        }), e.ui.plugin = {
            add: function (t, n, r) {
                var i, s = e.ui[t].prototype;
                for (i in r) s.plugins[i] = s.plugins[i] || [], s.plugins[i].push([n, r[i]])
            },
            call: function (e, t, n, r) {
                var i, s = e.plugins[t];
                if (s && (r || e.element[0].parentNode && 11 !== e.element[0].parentNode.nodeType))
                    for (i = 0; i < s.length; i++) e.options[s[i][0]] && s[i][1].apply(e.element, n)
            }
        }
    }(e),
    function (e, t) {
        var i = function (t, n) {
            var r = t.parent(),
                i = [],
                s = r.children(":jqmData(role='header')"),
                o = t.children(":jqmData(role='header')"),
                u = r.children(":jqmData(role='footer')"),
                a = t.children(":jqmData(role='footer')");
            return 0 === o.length && s.length > 0 && (i = i.concat(s.toArray())), 0 === a.length && u.length > 0 && (i = i.concat(u.toArray())), e.each(i, function (t, r) {
                n -= e(r).outerHeight()
            }), Math.max(0, n)
        };
        e.extend(e.mobile, {
            window: e(t),
            document: e(n),
            keyCode: e.ui.keyCode,
            behaviors: {},
            silentScroll: function (n) {
                "number" !== e.type(n) && (n = e.mobile.defaultHomeScroll), e.event.special.scrollstart.enabled = !1, setTimeout(function () {
                    t.scrollTo(0, n), e.mobile.document.trigger("silentscroll", {
                        x: 0,
                        y: n
                    })
                }, 20), setTimeout(function () {
                    e.event.special.scrollstart.enabled = !0
                }, 150)
            },
            getClosestBaseUrl: function (t) {
                var n = e(t).closest(".ui-page").jqmData("url"),
                    r = e.mobile.path.documentBase.hrefNoHash;
                return e.mobile.dynamicBaseEnabled && n && e.mobile.path.isPath(n) || (n = r), e.mobile.path.makeUrlAbsolute(n, r)
            },
            removeActiveLinkClass: function (t) {
                !!e.mobile.activeClickedLink && (!e.mobile.activeClickedLink.closest("." + e.mobile.activePageClass).length || t) && e.mobile.activeClickedLink.removeClass(e.mobile.activeBtnClass), e.mobile.activeClickedLink = null
            },
            getInheritedTheme: function (e, t) {
                for (var s, o, n = e[0], r = "", i = /ui-(bar|body|overlay)-([a-z])\b/; n && (s = n.className || "", !(s && (o = i.exec(s)) && (r = o[2])));) n = n.parentNode;
                return r || t || "a"
            },
            enhanceable: function (e) {
                return this.haveParents(e, "enhance")
            },
            hijackable: function (e) {
                return this.haveParents(e, "ajax")
            },
            haveParents: function (t, n) {
                if (!e.mobile.ignoreContentEnabled) return t;
                var s, o, u, a, f, r = t.length,
                    i = e();
                for (a = 0; r > a; a++) {
                    for (o = t.eq(a), u = !1, s = t[a]; s;) {
                        if (f = s.getAttribute ? s.getAttribute("data-" + e.mobile.ns + n) : "", "false" === f) {
                            u = !0;
                            break
                        }
                        s = s.parentNode
                    }
                    u || (i = i.add(o))
                }
                return i
            },
            getScreenHeight: function () {
                return t.innerHeight || e.mobile.window.height()
            },
            resetActivePageHeight: function (t) {
                var n = e("." + e.mobile.activePageClass),
                    r = n.height(),
                    s = n.outerHeight(!0);
                t = i(n, "number" == typeof t ? t : e.mobile.getScreenHeight()), n.css("min-height", t - (s - r))
            },
            loading: function () {
                var t = this.loading._widget || e(e.mobile.loader.prototype.defaultHtml).loader(),
                    n = t.loader.apply(t, arguments);
                return this.loading._widget = t, n
            }
        }), e.addDependents = function (t, n) {
            var r = e(t),
                i = r.jqmData("dependents") || e();
            r.jqmData("dependents", e(i).add(n))
        }, e.fn.extend({
            removeWithDependents: function () {
                e.removeWithDependents(this)
            },
            enhanceWithin: function () {
                var t, n = {},
                    r = e.mobile.page.prototype.keepNativeSelector(),
                    i = this;
                e.mobile.nojs && e.mobile.nojs(this), e.mobile.links && e.mobile.links(this), e.mobile.degradeInputsWithin && e.mobile.degradeInputsWithin(this), e.fn.buttonMarkup && this.find(e.fn.buttonMarkup.initSelector).not(r).jqmEnhanceable().buttonMarkup(), e.fn.fieldcontain && this.find(":jqmData(role='fieldcontain')").not(r).jqmEnhanceable().fieldcontain(), e.each(e.mobile.widgets, function (t, s) {
                    if (s.initSelector) {
                        var o = e.mobile.enhanceable(i.find(s.initSelector));
                        o.length > 0 && (o = o.not(r)), o.length > 0 && (n[s.prototype.widgetName] = o)
                    }
                });
                for (t in n) n[t][t]();
                return this
            },
            addDependents: function (t) {
                e.addDependents(this, t)
            },
            getEncodedText: function () {
                return e("<a>").text(this.text()).html()
            },
            jqmEnhanceable: function () {
                return e.mobile.enhanceable(this)
            },
            jqmHijackable: function () {
                return e.mobile.hijackable(this)
            }
        }), e.removeWithDependents = function (t) {
            var n = e(t);
            (n.jqmData("dependents") || e()).remove(), n.remove()
        }, e.addDependents = function (t, n) {
            var r = e(t),
                i = r.jqmData("dependents") || e();
            r.jqmData("dependents", e(i).add(n))
        }, e.find.matches = function (t, n) {
            return e.find(t, null, null, n)
        }, e.find.matchesSelector = function (t, n) {
            return e.find(n, null, null, [t]).length > 0
        }
    }(e, this),
    function (e) {
        t.matchMedia = t.matchMedia || function (e) {
            var n, r = e.documentElement,
                i = r.firstElementChild || r.firstChild,
                s = e.createElement("body"),
                o = e.createElement("div");
            return o.id = "mq-test-1", o.style.cssText = "position:absolute;top:-100em", s.style.background = "none", s.appendChild(o),
                function (e) {
                    return o.innerHTML = '&shy;<style media="' + e + '"> #mq-test-1 { width: 42px; }</style>', r.insertBefore(s, i), n = 42 === o.offsetWidth, r.removeChild(s), {
                        matches: n,
                        media: e
                    }
                }
        }(n), e.mobile.media = function (e) {
            return t.matchMedia(e).matches
        }
    }(e),
    function (e) {
        var r = {
            touch: "ontouchend" in n
        };
        e.mobile.support = e.mobile.support || {}, e.extend(e.support, r), e.extend(e.mobile.support, r)
    }(e),
    function (e) {
        e.extend(e.support, {
            orientation: "orientation" in t && "onorientationchange" in t
        })
    }(e),
    function (e, r) {
        function i(e) {
            var i, t = e.charAt(0).toUpperCase() + e.substr(1),
                n = (e + " " + u.join(t + " ") + t).split(" ");
            for (i in n)
                if (o[n[i]] !== r) return !0
        }

        function h() {
            var n = t,
                r = !(!n.document.createElementNS || !n.document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGRect || n.opera && -1 === navigator.userAgent.indexOf("Chrome")),
                i = function (t) {
                    (!t || !r) && e("html").addClass("ui-nosvg")
                },
                s = new n.Image;
            s.onerror = function () {
                i(!1)
            }, s.onload = function () {
                i(1 === s.width && 1 === s.height)
            }, s.src = ""
        }

        function p() {
            var a, f, l, i = "transform-3d",
                o = e.mobile.media("(-" + u.join("-" + i + "),(-") + "-" + i + "),(" + i + ")");
            if (o) return !!o;
            a = n.createElement("div"), f = {
                MozTransform: "-moz-transform",
                transform: "transform"
            }, s.append(a);
            for (l in f) a.style[l] !== r && (a.style[l] = "translate3d( 100px, 1px, 1px )", o = t.getComputedStyle(a).getPropertyValue(f[l]));
            return !!o && "none" !== o
        }

        function d() {
            var o, u, t = location.protocol + "//" + location.host + location.pathname + "ui-dir/",
                n = e("head base"),
                r = null,
                i = "";
            return n.length ? i = n.attr("href") : n = r = e("<base>", {
                href: t
            }).appendTo("head"), o = e("<a href='testurl' />").prependTo(s), u = o[0].href, n[0].href = i || location.pathname, r && r.remove(), 0 === u.indexOf(t)
        }

        function v() {
            var s, e = n.createElement("x"),
                r = n.documentElement,
                i = t.getComputedStyle;
            return "pointerEvents" in e.style ? (e.style.pointerEvents = "auto", e.style.pointerEvents = "x", r.appendChild(e), s = i && "auto" === i(e, "").pointerEvents, r.removeChild(e), !!s) : !1
        }

        function m() {
            var e = n.createElement("div");
            return "undefined" != typeof e.getBoundingClientRect
        }

        function g() {
            var e = t,
                n = navigator.userAgent,
                r = navigator.platform,
                i = n.match(/AppleWebKit\/([0-9]+)/),
                s = !!i && i[1],
                o = n.match(/Fennec\/([0-9]+)/),
                u = !!o && o[1],
                a = n.match(/Opera Mobi\/([0-9]+)/),
                f = !!a && a[1];
            return (r.indexOf("iPhone") > -1 || r.indexOf("iPad") > -1 || r.indexOf("iPod") > -1) && s && 534 > s || e.operamini && "[object OperaMini]" === {}.toString.call(e.operamini) || a && 7458 > f || n.indexOf("Android") > -1 && s && 533 > s || u && 6 > u || "palmGetResource" in t && s && 534 > s || n.indexOf("MeeGo") > -1 && n.indexOf("NokiaBrowser/8.5.0") > -1 ? !1 : !0
        }
        var c, s = e("<body>").prependTo("html"),
            o = s[0].style,
            u = ["Webkit", "Moz", "O"],
            a = "palmGetResource" in t,
            f = t.operamini && "[object OperaMini]" === {}.toString.call(t.operamini),
            l = t.blackberry && !i("-webkit-transform");
        e.extend(e.mobile, {
            browser: {}
        }), e.mobile.browser.oldIE = function () {
            var e = 3,
                t = n.createElement("div"),
                r = t.all || [];
            do t.innerHTML = "<!--[if gt IE " + ++e + "]><br><![endif]-->"; while (r[0]);
            return e > 4 ? e : !e
        }(), e.extend(e.support, {
            pushState: "pushState" in history && "replaceState" in history && !(t.navigator.userAgent.indexOf("Firefox") >= 0 && t.top !== t) && -1 === t.navigator.userAgent.search(/CriOS/),
            mediaquery: e.mobile.media("only all"),
            cssPseudoElement: !!i("content"),
            touchOverflow: !!i("overflowScrolling"),
            cssTransform3d: p(),
            boxShadow: !!i("boxShadow") && !l,
            fixedPosition: g(),
            scrollTop: ("pageXOffset" in t || "scrollTop" in n.documentElement || "scrollTop" in s[0]) && !a && !f,
            dynamicBaseTag: d(),
            cssPointerEvents: v(),
            boundingRect: m(),
            inlineSVG: h
        }), s.remove(), c = function () {
            var e = t.navigator.userAgent;
            return e.indexOf("Nokia") > -1 && (e.indexOf("Symbian/3") > -1 || e.indexOf("Series60/5") > -1) && e.indexOf("AppleWebKit") > -1 && e.match(/(BrowserNG|NokiaBrowser)\/7\.[0-3]/)
        }(), e.mobile.gradeA = function () {
            return (e.support.mediaquery && e.support.cssPseudoElement || e.mobile.browser.oldIE && e.mobile.browser.oldIE >= 8) && (e.support.boundingRect || null !== e.fn.jquery.match(/1\.[0-7+]\.[0-9+]?/))
        }, e.mobile.ajaxBlacklist = t.blackberry && !t.WebKitPoint || f || c, c && e(function () {
            e("head link[rel='stylesheet']").attr("rel", "alternate stylesheet").attr("rel", "stylesheet")
        }), e.support.boxShadow || e("html").addClass("ui-noboxshadow")
    }(e),
    function (e, t) {
        var r, n = e.mobile.window,
            i = function () {};
        e.event.special.beforenavigate = {
            setup: function () {
                n.on("navigate", i)
            },
            teardown: function () {
                n.off("navigate", i)
            }
        }, e.event.special.navigate = r = {
            bound: !1,
            pushStateEnabled: !0,
            originalEventName: t,
            isPushStateEnabled: function () {
                return e.support.pushState && e.mobile.pushStateEnabled === !0 && this.isHashChangeEnabled()
            },
            isHashChangeEnabled: function () {
                return e.mobile.hashListeningEnabled === !0
            },
            popstate: function (t) {
                var r = new e.Event("navigate"),
                    i = new e.Event("beforenavigate"),
                    s = t.originalEvent.state || {};
                i.originalEvent = t, n.trigger(i), i.isDefaultPrevented() || (t.historyState && e.extend(s, t.historyState), r.originalEvent = t, setTimeout(function () {
                    n.trigger(r, {
                        state: s
                    })
                }, 0))
            },
            hashchange: function (t) {
                var r = new e.Event("navigate"),
                    i = new e.Event("beforenavigate");
                i.originalEvent = t, n.trigger(i), i.isDefaultPrevented() || (r.originalEvent = t, n.trigger(r, {
                    state: t.hashchangeState || {}
                }))
            },
            setup: function () {
                r.bound || (r.bound = !0, r.isPushStateEnabled() ? (r.originalEventName = "popstate", n.bind("popstate.navigate", r.popstate)) : r.isHashChangeEnabled() && (r.originalEventName = "hashchange", n.bind("hashchange.navigate", r.hashchange)))
            }
        }
    }(e),
    function (e) {
        e.event.special.throttledresize = {
            setup: function () {
                e(this).bind("resize", n)
            },
            teardown: function () {
                e(this).unbind("resize", n)
            }
        };
        var i, s, o, t = 250,
            n = function () {
                s = (new Date).getTime(), o = s - r, o >= t ? (r = s, e(this).trigger("throttledresize")) : (i && clearTimeout(i), i = setTimeout(n, t - o))
            },
            r = 0
    }(e),
    function (e, t) {
        function p() {
            var e = s();
            e !== o && (o = e, r.trigger(i))
        }
        var s, o, u, a, l, c, h, r = e(t),
            i = "orientationchange",
            f = {
                0: !0,
                180: !0
            };
        e.support.orientation && (l = t.innerWidth || r.width(), c = t.innerHeight || r.height(), h = 50, u = l > c && l - c > h, a = f[t.orientation], (u && a || !u && !a) && (f = {
            "-90": !0,
            90: !0
        })), e.event.special.orientationchange = e.extend({}, e.event.special.orientationchange, {
            setup: function () {
                return e.support.orientation && !e.event.special.orientationchange.disabled ? !1 : (o = s(), r.bind("throttledresize", p), void 0)
            },
            teardown: function () {
                return e.support.orientation && !e.event.special.orientationchange.disabled ? !1 : (r.unbind("throttledresize", p), void 0)
            },
            add: function (e) {
                var t = e.handler;
                e.handler = function (e) {
                    return e.orientation = s(), t.apply(this, arguments)
                }
            }
        }), e.event.special.orientationchange.orientation = s = function () {
            var r = !0,
                i = n.documentElement;
            return r = e.support.orientation ? f[t.orientation] : i && i.clientWidth / i.clientHeight < 1.1, r ? "portrait" : "landscape"
        }, e.fn[i] = function (e) {
            return e ? this.bind(i, e) : this.trigger(i)
        }, e.attrFn && (e.attrFn[i] = !0)
    }(e, this),
    function (e, t, n, r) {
        function T(e) {
            for (; e && "undefined" != typeof e.originalEvent;) e = e.originalEvent;
            return e
        }

        function N(t, n) {
            var s, o, a, l, c, h, p, d, v, i = t.type;
            if (t = e.Event(t), t.type = n, s = t.originalEvent, o = e.event.props, i.search(/^(mouse|click)/) > -1 && (o = f), s)
                for (p = o.length, l; p;) l = o[--p], t[l] = s[l];
            if (i.search(/mouse(down|up)|click/) > -1 && !t.which && (t.which = 1), -1 !== i.search(/^touch/) && (a = T(s), i = a.touches, c = a.changedTouches, h = i && i.length ? i[0] : c && c.length ? c[0] : r, h))
                for (d = 0, v = u.length; v > d; d++) l = u[d], t[l] = h[l];
            return t
        }

        function C(t) {
            for (var r, s, n = {}; t;) {
                r = e.data(t, i);
                for (s in r) r[s] && (n[s] = n.hasVirtualBinding = !0);
                t = t.parentNode
            }
            return n
        }

        function k(t, n) {
            for (var r; t;) {
                if (r = e.data(t, i), r && (!n || r[n])) return t;
                t = t.parentNode
            }
            return null
        }

        function L() {
            g = !1
        }

        function A() {
            g = !0
        }

        function O() {
            E = 0, v.length = 0, m = !1, A()
        }

        function M() {
            L()
        }

        function _() {
            D(), c = setTimeout(function () {
                c = 0, O()
            }, e.vmouse.resetTimerDuration)
        }

        function D() {
            c && (clearTimeout(c), c = 0)
        }

        function P(t, n, r) {
            var i;
            return (r && r[t] || !r && k(n.target, t)) && (i = N(n, t), e(n.target).trigger(i)), i
        }

        function H(t) {
            var r, n = e.data(t.target, s);
            !m && (!E || E !== n) && (r = P("v" + t.type, t), r && (r.isDefaultPrevented() && t.preventDefault(), r.isPropagationStopped() && t.stopPropagation(), r.isImmediatePropagationStopped() && t.stopImmediatePropagation()))
        }

        function B(t) {
            var r, i, o, n = T(t).touches;
            n && 1 === n.length && (r = t.target, i = C(r), i.hasVirtualBinding && (E = w++, e.data(r, s, E), D(), M(), d = !1, o = T(t).touches[0], h = o.pageX, p = o.pageY, P("vmouseover", t, i), P("vmousedown", t, i)))
        }

        function j(e) {
            g || (d || P("vmousecancel", e, C(e.target)), d = !0, _())
        }

        function F(t) {
            if (!g) {
                var n = T(t).touches[0],
                    r = d,
                    i = e.vmouse.moveDistanceThreshold,
                    s = C(t.target);
                d = d || Math.abs(n.pageX - h) > i || Math.abs(n.pageY - p) > i, d && !r && P("vmousecancel", t, s), P("vmousemove", t, s), _()
            }
        }

        function I(e) {
            if (!g) {
                A();
                var n, r, t = C(e.target);
                P("vmouseup", e, t), d || (n = P("vclick", e, t), n && n.isDefaultPrevented() && (r = T(e).changedTouches[0], v.push({
                    touchID: E,
                    x: r.clientX,
                    y: r.clientY
                }), m = !0)), P("vmouseout", e, t), d = !1, _()
            }
        }

        function q(t) {
            var r, n = e.data(t, i);
            if (n)
                for (r in n)
                    if (n[r]) return !0;
            return !1
        }

        function R() {}

        function U(t) {
            var n = t.substr(1);
            return {
                setup: function () {
                    q(this) || e.data(this, i, {});
                    var r = e.data(this, i);
                    r[t] = !0, l[t] = (l[t] || 0) + 1, 1 === l[t] && b.bind(n, H), e(this).bind(n, R), y && (l.touchstart = (l.touchstart || 0) + 1, 1 === l.touchstart && b.bind("touchstart", B).bind("touchend", I).bind("touchmove", F).bind("scroll", j))
                },
                teardown: function () {
                    --l[t], l[t] || b.unbind(n, H), y && (--l.touchstart, l.touchstart || b.unbind("touchstart", B).unbind("touchmove", F).unbind("touchend", I).unbind("scroll", j));
                    var r = e(this),
                        s = e.data(this, i);
                    s && (s[t] = !1), r.unbind(n, R), q(this) || r.removeData(i)
                }
            }
        }
        var S, x, i = "virtualMouseBindings",
            s = "virtualTouchID",
            o = "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split(" "),
            u = "clientX clientY pageX pageY screenX screenY".split(" "),
            a = e.event.mouseHooks ? e.event.mouseHooks.props : [],
            f = e.event.props.concat(a),
            l = {},
            c = 0,
            h = 0,
            p = 0,
            d = !1,
            v = [],
            m = !1,
            g = !1,
            y = "addEventListener" in n,
            b = e(n),
            w = 1,
            E = 0;
        for (e.vmouse = {
            moveDistanceThreshold: 10,
            clickDistanceThreshold: 10,
            resetTimerDuration: 1500
        }, x = 0; x < o.length; x++) e.event.special[o[x]] = U(o[x]);
        y && n.addEventListener("click", function (t) {
            var i, o, u, a, f, l, n = v.length,
                r = t.target;
            if (n)
                for (i = t.clientX, o = t.clientY, S = e.vmouse.clickDistanceThreshold, u = r; u;) {
                    for (a = 0; n > a; a++)
                        if (f = v[a], l = 0, u === r && Math.abs(f.x - i) < S && Math.abs(f.y - o) < S || e.data(u, s) === f.touchID) return t.preventDefault(), t.stopPropagation(), void 0;
                    u = u.parentNode
                }
        }, !0)
    }(e, t, n),
    function (e, t, r) {
        function l(t, n, i, s) {
            var o = i.type;
            i.type = n, s ? e.event.trigger(i, r, t) : e.event.dispatch.call(t, i), i.type = o
        }
        var i = e(n),
            s = e.mobile.support.touch,
            o = "touchmove scroll",
            u = s ? "touchstart" : "mousedown",
            a = s ? "touchend" : "mouseup",
            f = s ? "touchmove" : "mousemove";
        e.each("touchstart touchmove touchend tap taphold swipe swipeleft swiperight scrollstart scrollstop".split(" "), function (t, n) {
            e.fn[n] = function (e) {
                return e ? this.bind(n, e) : this.trigger(n)
            }, e.attrFn && (e.attrFn[n] = !0)
        }), e.event.special.scrollstart = {
            enabled: !0,
            setup: function () {
                function s(e, n) {
                    r = n, l(t, r ? "scrollstart" : "scrollstop", e)
                }
                var r, i, t = this,
                    n = e(t);
                n.bind(o, function (t) {
                    e.event.special.scrollstart.enabled && (r || s(t, !0), clearTimeout(i), i = setTimeout(function () {
                        s(t, !1)
                    }, 50))
                })
            },
            teardown: function () {
                e(this).unbind(o)
            }
        }, e.event.special.tap = {
            tapholdThreshold: 750,
            emitTapOnTaphold: !0,
            setup: function () {
                var t = this,
                    n = e(t),
                    r = !1;
                n.bind("vmousedown", function (s) {
                    function a() {
                        clearTimeout(u)
                    }

                    function f() {
                        a(), n.unbind("vclick", c).unbind("vmouseup", a), i.unbind("vmousecancel", f)
                    }

                    function c(e) {
                        f(), r || o !== e.target ? r && e.stopPropagation() : l(t, "tap", e)
                    }
                    if (r = !1, s.which && 1 !== s.which) return !1;
                    var u, o = s.target;
                    n.bind("vmouseup", a).bind("vclick", c), i.bind("vmousecancel", f), u = setTimeout(function () {
                        e.event.special.tap.emitTapOnTaphold || (r = !0), l(t, "taphold", e.Event("taphold", {
                            target: o
                        }))
                    }, e.event.special.tap.tapholdThreshold)
                })
            },
            teardown: function () {
                e(this).unbind("vmousedown").unbind("vclick").unbind("vmouseup"), i.unbind("vmousecancel")
            }
        }, e.event.special.swipe = {
            scrollSupressionThreshold: 30,
            durationThreshold: 1e3,
            horizontalDistanceThreshold: 30,
            verticalDistanceThreshold: 30,
            getLocation: function (e) {
                var n = t.pageXOffset,
                    r = t.pageYOffset,
                    i = e.clientX,
                    s = e.clientY;
                return 0 === e.pageY && Math.floor(s) > Math.floor(e.pageY) || 0 === e.pageX && Math.floor(i) > Math.floor(e.pageX) ? (i -= n, s -= r) : (s < e.pageY - r || i < e.pageX - n) && (i = e.pageX - n, s = e.pageY - r), {
                    x: i,
                    y: s
                }
            },
            start: function (t) {
                var n = t.originalEvent.touches ? t.originalEvent.touches[0] : t,
                    r = e.event.special.swipe.getLocation(n);
                return {
                    time: (new Date).getTime(),
                    coords: [r.x, r.y],
                    origin: e(t.target)
                }
            },
            stop: function (t) {
                var n = t.originalEvent.touches ? t.originalEvent.touches[0] : t,
                    r = e.event.special.swipe.getLocation(n);
                return {
                    time: (new Date).getTime(),
                    coords: [r.x, r.y]
                }
            },
            handleSwipe: function (t, n, r, i) {
                if (n.time - t.time < e.event.special.swipe.durationThreshold && Math.abs(t.coords[0] - n.coords[0]) > e.event.special.swipe.horizontalDistanceThreshold && Math.abs(t.coords[1] - n.coords[1]) < e.event.special.swipe.verticalDistanceThreshold) {
                    var s = t.coords[0] > n.coords[0] ? "swipeleft" : "swiperight";
                    return l(r, "swipe", e.Event("swipe", {
                        target: i,
                        swipestart: t,
                        swipestop: n
                    }), !0), l(r, s, e.Event(s, {
                        target: i,
                        swipestart: t,
                        swipestop: n
                    }), !0), !0
                }
                return !1
            },
            eventInProgress: !1,
            setup: function () {
                var t, n = this,
                    r = e(n),
                    s = {};
                t = e.data(this, "mobile-events"), t || (t = {
                    length: 0
                }, e.data(this, "mobile-events", t)), t.length++, t.swipe = s, s.start = function (t) {
                    if (!e.event.special.swipe.eventInProgress) {
                        e.event.special.swipe.eventInProgress = !0;
                        var r, o = e.event.special.swipe.start(t),
                            u = t.target,
                            l = !1;
                        s.move = function (t) {
                            o && (r = e.event.special.swipe.stop(t), l || (l = e.event.special.swipe.handleSwipe(o, r, n, u), l && (e.event.special.swipe.eventInProgress = !1)), Math.abs(o.coords[0] - r.coords[0]) > e.event.special.swipe.scrollSupressionThreshold && t.preventDefault())
                        }, s.stop = function () {
                            l = !0, e.event.special.swipe.eventInProgress = !1, i.off(f, s.move), s.move = null
                        }, i.on(f, s.move).one(a, s.stop)
                    }
                }, r.on(u, s.start)
            },
            teardown: function () {
                var t, n;
                t = e.data(this, "mobile-events"), t && (n = t.swipe, delete t.swipe, t.length--, 0 === t.length && e.removeData(this, "mobile-events")), n && (n.start && e(this).off(u, n.start), n.move && i.off(f, n.move), n.stop && i.off(a, n.stop))
            }
        }, e.each({
            scrollstop: "scrollstart",
            taphold: "tap",
            swipeleft: "swipe",
            swiperight: "swipe"
        }, function (t, n) {
            e.event.special[t] = {
                setup: function () {
                    e(this).bind(n, e.noop)
                },
                teardown: function () {
                    e(this).unbind(n)
                }
            }
        })
    }(e, this),
    function (e, t) {
        var r = {
                animation: {},
                transition: {}
            },
            i = n.createElement("a"),
            s = ["", "webkit-", "moz-", "o-"];
        e.each(["animation", "transition"], function (n, o) {
            var u = 0 === n ? o + "-name" : o;
            e.each(s, function (n, s) {
                return i.style[e.camelCase(s + u)] !== t ? (r[o].prefix = s, !1) : void 0
            }), r[o].duration = e.camelCase(r[o].prefix + o + "-duration"), r[o].event = e.camelCase(r[o].prefix + o + "-end"), "" === r[o].prefix && (r[o].event = r[o].event.toLowerCase())
        }), e.support.cssTransitions = r.transition.prefix !== t, e.support.cssAnimations = r.animation.prefix !== t, e(i).remove(), e.fn.animationComplete = function (i, s, o) {
            var u, a, f = this,
                l = s && "animation" !== s ? "transition" : "animation";
            return e.support.cssTransitions && "transition" === l || e.support.cssAnimations && "animation" === l ? (o === t && (e(this).context !== n && (a = 3e3 * parseFloat(e(this).css(r[l].duration))), (0 === a || a === t || isNaN(a)) && (a = e.fn.animationComplete.defaultDuration)), u = setTimeout(function () {
                e(f).off(r[l].event), i.apply(f)
            }, a), e(this).one(r[l].event, function () {
                clearTimeout(u), i.call(this, arguments)
            })) : (setTimeout(e.proxy(i, this), 0), e(this))
        }, e.fn.animationComplete.defaultDuration = 1e3
    }(e),
    function (e) {
        e.fn.grid = function (t) {
            return this.each(function () {
                var u, a, n = e(this),
                    r = e.extend({
                        grid: null
                    }, t),
                    i = n.children(),
                    s = {
                        solo: 1,
                        a: 2,
                        b: 3,
                        c: 4,
                        d: 5
                    },
                    o = r.grid;
                if (!o)
                    if (i.length <= 5)
                        for (a in s) s[a] === i.length && (o = a);
                    else o = "a", n.addClass("ui-grid-duo");
                u = s[o], n.addClass("ui-grid-" + o), i.filter(":nth-child(" + u + "n+1)").addClass("ui-block-a"), u > 1 && i.filter(":nth-child(" + u + "n+2)").addClass("ui-block-b"), u > 2 && i.filter(":nth-child(" + u + "n+3)").addClass("ui-block-c"), u > 3 && i.filter(":nth-child(" + u + "n+4)").addClass("ui-block-d"), u > 4 && i.filter(":nth-child(" + u + "n+5)").addClass("ui-block-e")
            })
        }
    }(e),
    function (e, n) {
        var r, i, s = "&ui-state=dialog";
        e.mobile.path = r = {
            uiStateKey: "&ui-state",
            urlParseRE: /^\s*(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,
            getLocation: function (e) {
                var t = e ? this.parseUrl(e) : location,
                    n = this.parseUrl(e || location.href).hash;
                return n = "#" === n ? "" : n, t.protocol + "//" + t.host + t.pathname + t.search + n
            },
            getDocumentUrl: function (t) {
                return t ? e.extend({}, r.documentUrl) : r.documentUrl.href
            },
            parseLocation: function () {
                return this.parseUrl(this.getLocation())
            },
            parseUrl: function (t) {
                if ("object" === e.type(t)) return t;
                var n = r.urlParseRE.exec(t || "") || [];
                return {
                    href: n[0] || "",
                    hrefNoHash: n[1] || "",
                    hrefNoSearch: n[2] || "",
                    domain: n[3] || "",
                    protocol: n[4] || "",
                    doubleSlash: n[5] || "",
                    authority: n[6] || "",
                    username: n[8] || "",
                    password: n[9] || "",
                    host: n[10] || "",
                    hostname: n[11] || "",
                    port: n[12] || "",
                    pathname: n[13] || "",
                    directory: n[14] || "",
                    filename: n[15] || "",
                    search: n[16] || "",
                    hash: n[17] || ""
                }
            },
            makePathAbsolute: function (e, t) {
                var n, r, i, s;
                if (e && "/" === e.charAt(0)) return e;
                for (e = e || "", t = t ? t.replace(/^\/|(\/[^\/]*|[^\/]+)$/g, "") : "", n = t ? t.split("/") : [], r = e.split("/"), i = 0; i < r.length; i++) switch (s = r[i]) {
                case ".":
                    break;
                case "..":
                    n.length && n.pop();
                    break;
                default:
                    n.push(s)
                }
                return "/" + n.join("/")
            },
            isSameDomain: function (e, t) {
                return r.parseUrl(e).domain === r.parseUrl(t).domain
            },
            isRelativeUrl: function (e) {
                return "" === r.parseUrl(e).protocol
            },
            isAbsoluteUrl: function (e) {
                return "" !== r.parseUrl(e).protocol
            },
            makeUrlAbsolute: function (e, t) {
                if (!r.isRelativeUrl(e)) return e;
                t === n && (t = this.documentBase);
                var i = r.parseUrl(e),
                    s = r.parseUrl(t),
                    o = i.protocol || s.protocol,
                    u = i.protocol ? i.doubleSlash : i.doubleSlash || s.doubleSlash,
                    a = i.authority || s.authority,
                    f = "" !== i.pathname,
                    l = r.makePathAbsolute(i.pathname || s.filename, s.pathname),
                    c = i.search || !f && s.search || "",
                    h = i.hash;
                return o + u + a + l + c + h
            },
            addSearchParams: function (t, n) {
                var i = r.parseUrl(t),
                    s = "object" == typeof n ? e.param(n) : n,
                    o = i.search || "?";
                return i.hrefNoSearch + o + ("?" !== o.charAt(o.length - 1) ? "&" : "") + s + (i.hash || "")
            },
            convertUrlToDataUrl: function (e) {
                var n = r.parseUrl(e);
                return r.isEmbeddedPage(n) ? n.hash.split(s)[0].replace(/^#/, "").replace(/\?.*$/, "") : r.isSameDomain(n, this.documentBase) ? n.hrefNoHash.replace(this.documentBase.domain, "").split(s)[0] : t.decodeURIComponent(e)
            },
            get: function (e) {
                return e === n && (e = r.parseLocation().hash), r.stripHash(e).replace(/[^\/]*\.[^\/*]+$/, "")
            },
            set: function (e) {
                location.hash = e
            },
            isPath: function (e) {
                return /\//.test(e)
            },
            clean: function (e) {
                return e.replace(this.documentBase.domain, "")
            },
            stripHash: function (e) {
                return e.replace(/^#/, "")
            },
            stripQueryParams: function (e) {
                return e.replace(/\?.*$/, "")
            },
            cleanHash: function (e) {
                return r.stripHash(e.replace(/\?.*$/, "").replace(s, ""))
            },
            isHashValid: function (e) {
                return /^#[^#]+$/.test(e)
            },
            isExternal: function (e) {
                var t = r.parseUrl(e);
                return t.protocol && t.domain !== this.documentUrl.domain ? !0 : !1
            },
            hasProtocol: function (e) {
                return /^(:?\w+:)/.test(e)
            },
            isEmbeddedPage: function (e) {
                var t = r.parseUrl(e);
                return "" !== t.protocol ? !this.isPath(t.hash) && t.hash && (t.hrefNoHash === this.documentUrl.hrefNoHash || this.documentBaseDiffers && t.hrefNoHash === this.documentBase.hrefNoHash) : /^#/.test(t.href)
            },
            squash: function (e, t) {
                var n, i, s, o, u = this.isPath(e),
                    a = this.parseUrl(e),
                    f = a.hash,
                    l = "";
                return t = t || (r.isPath(e) ? r.getLocation() : r.getDocumentUrl()), i = u ? r.stripHash(e) : e, i = r.isPath(a.hash) ? r.stripHash(a.hash) : i, o = i.indexOf(this.uiStateKey), o > -1 && (l = i.slice(o), i = i.slice(0, o)), n = r.makeUrlAbsolute(i, t), s = this.parseUrl(n).search, u ? ((r.isPath(f) || 0 === f.replace("#", "").indexOf(this.uiStateKey)) && (f = ""), l && -1 === f.indexOf(this.uiStateKey) && (f += l), -1 === f.indexOf("#") && "" !== f && (f = "#" + f), n = r.parseUrl(n), n = n.protocol + "//" + n.host + n.pathname + s + f) : n += n.indexOf("#") > -1 ? l : "#" + l, n
            },
            isPreservableHash: function (e) {
                return 0 === e.replace("#", "").indexOf(this.uiStateKey)
            },
            hashToSelector: function (e) {
                var t = "#" === e.substring(0, 1);
                return t && (e = e.substring(1)), (t ? "#" : "") + e.replace(/([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g, "\\$1")
            },
            getFilePath: function (t) {
                var n = "&" + e.mobile.subPageUrlKey;
                return t && t.split(n)[0].split(s)[0]
            },
            isFirstPageUrl: function (t) {
                var i = r.parseUrl(r.makeUrlAbsolute(t, this.documentBase)),
                    s = i.hrefNoHash === this.documentUrl.hrefNoHash || this.documentBaseDiffers && i.hrefNoHash === this.documentBase.hrefNoHash,
                    o = e.mobile.firstPage,
                    u = o && o[0] ? o[0].id : n;
                return s && (!i.hash || "#" === i.hash || u && i.hash.replace(/^#/, "") === u)
            },
            isPermittedCrossDomainRequest: function (t, n) {
                return e.mobile.allowCrossDomainPages && ("file:" === t.protocol || "content:" === t.protocol) && -1 !== n.search(/^https?:/)
            }
        }, r.documentUrl = r.parseLocation(), i = e("head").find("base"), r.documentBase = i.length ? r.parseUrl(r.makeUrlAbsolute(i.attr("href"), r.documentUrl.href)) : r.documentUrl, r.documentBaseDiffers = r.documentUrl.hrefNoHash !== r.documentBase.hrefNoHash, r.getDocumentBase = function (t) {
            return t ? e.extend({}, r.documentBase) : r.documentBase.href
        }, e.extend(e.mobile, {
            getDocumentUrl: r.getDocumentUrl,
            getDocumentBase: r.getDocumentBase
        })
    }(e),
    function (e) {
        e.mobile.links = function (t) {
            e(t).find("a").jqmEnhanceable().filter(":jqmData(rel='popup')[href][href!='']").each(function () {
                var e = this,
                    t = e.getAttribute("href").substring(1);
                t && (e.setAttribute("aria-haspopup", !0), e.setAttribute("aria-owns", t), e.setAttribute("aria-expanded", !1))
            }).end().not(".ui-btn, :jqmData(role='none'), :jqmData(role='nojs')").addClass("ui-link")
        }
    }(e),
    function (e, t) {
        e.mobile.History = function (e, t) {
            this.stack = e || [], this.activeIndex = t || 0
        }, e.extend(e.mobile.History.prototype, {
            getActive: function () {
                return this.stack[this.activeIndex]
            },
            getLast: function () {
                return this.stack[this.previousIndex]
            },
            getNext: function () {
                return this.stack[this.activeIndex + 1]
            },
            getPrev: function () {
                return this.stack[this.activeIndex - 1]
            },
            add: function (e, t) {
                t = t || {}, this.getNext() && this.clearForward(), t.hash && -1 === t.hash.indexOf("#") && (t.hash = "#" + t.hash), t.url = e, this.stack.push(t), this.activeIndex = this.stack.length - 1
            },
            clearForward: function () {
                this.stack = this.stack.slice(0, this.activeIndex + 1)
            },
            find: function (e, t, n) {
                t = t || this.stack;
                var r, i, o, s = t.length;
                for (i = 0; s > i; i++)
                    if (r = t[i], (decodeURIComponent(e) === decodeURIComponent(r.url) || decodeURIComponent(e) === decodeURIComponent(r.hash)) && (o = i, n)) return o;
                return o
            },
            closest: function (e) {
                var n, r = this.activeIndex;
                return n = this.find(e, this.stack.slice(0, r)), n === t && (n = this.find(e, this.stack.slice(r), !0), n = n === t ? n : n + r), n
            },
            direct: function (n) {
                var r = this.closest(n.url),
                    i = this.activeIndex;
                r !== t && (this.activeIndex = r, this.previousIndex = i), i > r ? (n.present || n.back || e.noop)(this.getActive(), "back") : r > i ? (n.present || n.forward || e.noop)(this.getActive(), "forward") : r === t && n.missing && n.missing(this.getActive())
            }
        })
    }(e),
    function (e) {
        var i = e.mobile.path,
            s = location.href;
        e.mobile.Navigator = function (t) {
            this.history = t, this.ignoreInitialHashChange = !0, e.mobile.window.bind({
                "popstate.history": e.proxy(this.popstate, this),
                "hashchange.history": e.proxy(this.hashchange, this)
            })
        }, e.extend(e.mobile.Navigator.prototype, {
            squash: function (r, s) {
                var o, u, a = i.isPath(r) ? i.stripHash(r) : r;
                return u = i.squash(r), o = e.extend({
                    hash: a,
                    url: u
                }, s), t.history.replaceState(o, o.title || n.title, u), o
            },
            hash: function (e, t) {
                var n, r, s, o;
                return n = i.parseUrl(e), r = i.parseLocation(), r.pathname + r.search === n.pathname + n.search ? s = n.hash ? n.hash : n.pathname + n.search : i.isPath(e) ? (o = i.parseUrl(t), s = o.pathname + o.search + (i.isPreservableHash(o.hash) ? o.hash.replace("#", "") : "")) : s = e, s
            },
            go: function (r, s, o) {
                var u, a, f, l, c = e.event.special.navigate.isPushStateEnabled();
                a = i.squash(r), f = this.hash(r, a), o && f !== i.stripHash(i.parseLocation().hash) && (this.preventNextHashChange = o), this.preventHashAssignPopState = !0, t.location.hash = f, this.preventHashAssignPopState = !1, u = e.extend({
                    url: a,
                    hash: f,
                    title: n.title
                }, s), c && (l = new e.Event("popstate"), l.originalEvent = {
                    type: "popstate",
                    state: null
                }, this.squash(r, u), o || (this.ignorePopState = !0, e.mobile.window.trigger(l))), this.history.add(u.url, u)
            },
            popstate: function (t) {
                var n, r;
                if (e.event.special.navigate.isPushStateEnabled()) return this.preventHashAssignPopState ? (this.preventHashAssignPopState = !1, t.stopImmediatePropagation(), void 0) : this.ignorePopState ? (this.ignorePopState = !1, void 0) : !t.originalEvent.state && 1 === this.history.stack.length && this.ignoreInitialHashChange && (this.ignoreInitialHashChange = !1, location.href === s) ? (t.preventDefault(), void 0) : (n = i.parseLocation().hash, !t.originalEvent.state && n ? (r = this.squash(n), this.history.add(r.url, r), t.historyState = r, void 0) : (this.history.direct({
                    url: (t.originalEvent.state || {}).url || n,
                    present: function (n, r) {
                        t.historyState = e.extend({}, n), t.historyState.direction = r
                    }
                }), void 0))
            },
            hashchange: function (t) {
                var r, s;
                if (e.event.special.navigate.isHashChangeEnabled() && !e.event.special.navigate.isPushStateEnabled()) return this.preventNextHashChange ? (this.preventNextHashChange = !1, t.stopImmediatePropagation(), void 0) : (r = this.history, s = i.parseLocation().hash, this.history.direct({
                    url: s,
                    present: function (n, r) {
                        t.hashchangeState = e.extend({}, n), t.hashchangeState.direction = r
                    },
                    missing: function () {
                        r.add(s, {
                            hash: s,
                            title: n.title
                        })
                    }
                }), void 0)
            }
        })
    }(e),
    function (e) {
        e.mobile.navigate = function (t, n, r) {
            e.mobile.navigate.navigator.go(t, n, r)
        }, e.mobile.navigate.history = new e.mobile.History, e.mobile.navigate.navigator = new e.mobile.Navigator(e.mobile.navigate.history);
        var n = e.mobile.path.parseLocation();
        e.mobile.navigate.history.add(n.href, {
            hash: n.hash
        })
    }(e),
    function (e) {
        var n = e("head").children("base"),
            r = {
                element: n.length ? n : e("<base>", {
                    href: e.mobile.path.documentBase.hrefNoHash
                }).prependTo(e("head")),
                linkSelector: "[src], link[href], a[rel='external'], :jqmData(ajax='false'), a[target]",
                set: function (t) {
                    e.mobile.dynamicBaseEnabled && e.support.dynamicBaseTag && r.element.attr("href", e.mobile.path.makeUrlAbsolute(t, e.mobile.path.documentBase))
                },
                rewrite: function (t, n) {
                    var i = e.mobile.path.get(t);
                    n.find(r.linkSelector).each(function (t, n) {
                        var r = e(n).is("[href]") ? "href" : e(n).is("[src]") ? "src" : "action",
                            s = e(n).attr(r);
                        s = s.replace(location.protocol + "//" + location.host + location.pathname, ""), /^(\w+:|#|\/)/.test(s) || e(n).attr(r, i + s)
                    })
                },
                reset: function () {
                    r.element.attr("href", e.mobile.path.documentBase.hrefNoSearch)
                }
            };
        e.mobile.base = r
    }(e),
    function (e, t) {
        var n = 0,
            r = Array.prototype.slice,
            i = e.cleanData;
        e.cleanData = function (t) {
            for (var r, n = 0; null != (r = t[n]); n++) try {
                e(r).triggerHandler("remove")
            } catch (s) {}
            i(t)
        }, e.widget = function (t, n, r) {
            var i, s, o, u, a = {},
                f = t.split(".")[0];
            return t = t.split(".")[1], i = f + "-" + t, r || (r = n, n = e.Widget), e.expr[":"][i.toLowerCase()] = function (t) {
                return !!e.data(t, i)
            }, e[f] = e[f] || {}, s = e[f][t], o = e[f][t] = function (e, t) {
                return this._createWidget ? (arguments.length && this._createWidget(e, t), void 0) : new o(e, t)
            }, e.extend(o, s, {
                version: r.version,
                _proto: e.extend({}, r),
                _childConstructors: []
            }), u = new n, u.options = e.widget.extend({}, u.options), e.each(r, function (t, r) {
                return e.isFunction(r) ? (a[t] = function () {
                    var e = function () {
                            return n.prototype[t].apply(this, arguments)
                        },
                        i = function (e) {
                            return n.prototype[t].apply(this, e)
                        };
                    return function () {
                        var s, t = this._super,
                            n = this._superApply;
                        return this._super = e, this._superApply = i, s = r.apply(this, arguments), this._super = t, this._superApply = n, s
                    }
                }(), void 0) : (a[t] = r, void 0)
            }), o.prototype = e.widget.extend(u, {
                widgetEventPrefix: s ? u.widgetEventPrefix || t : t
            }, a, {
                constructor: o,
                namespace: f,
                widgetName: t,
                widgetFullName: i
            }), s ? (e.each(s._childConstructors, function (t, n) {
                var r = n.prototype;
                e.widget(r.namespace + "." + r.widgetName, o, n._proto)
            }), delete s._childConstructors) : n._childConstructors.push(o), e.widget.bridge(t, o), o
        }, e.widget.extend = function (n) {
            for (var u, a, i = r.call(arguments, 1), s = 0, o = i.length; o > s; s++)
                for (u in i[s]) a = i[s][u], i[s].hasOwnProperty(u) && a !== t && (n[u] = e.isPlainObject(a) ? e.isPlainObject(n[u]) ? e.widget.extend({}, n[u], a) : e.widget.extend({}, a) : a);
            return n
        }, e.widget.bridge = function (n, i) {
            var s = i.prototype.widgetFullName || n;
            e.fn[n] = function (o) {
                var u = "string" == typeof o,
                    a = r.call(arguments, 1),
                    f = this;
                return o = !u && a.length ? e.widget.extend.apply(null, [o].concat(a)) : o, u ? this.each(function () {
                    var r, i = e.data(this, s);
                    return "instance" === o ? (f = i, !1) : i ? e.isFunction(i[o]) && "_" !== o.charAt(0) ? (r = i[o].apply(i, a), r !== i && r !== t ? (f = r && r.jquery ? f.pushStack(r.get()) : r, !1) : void 0) : e.error("no such method '" + o + "' for " + n + " widget instance") : e.error("cannot call methods on " + n + " prior to initialization; attempted to call method '" + o + "'")
                }) : this.each(function () {
                    var t = e.data(this, s);
                    t ? t.option(o || {})._init() : e.data(this, s, new i(o, this))
                }), f
            }
        }, e.Widget = function () {}, e.Widget._childConstructors = [], e.Widget.prototype = {
            widgetName: "widget",
            widgetEventPrefix: "",
            defaultElement: "<div>",
            options: {
                disabled: !1,
                create: null
            },
            _createWidget: function (t, r) {
                r = e(r || this.defaultElement || this)[0], this.element = e(r), this.uuid = n++, this.eventNamespace = "." + this.widgetName + this.uuid, this.options = e.widget.extend({}, this.options, this._getCreateOptions(), t), this.bindings = e(), this.hoverable = e(), this.focusable = e(), r !== this && (e.data(r, this.widgetFullName, this), this._on(!0, this.element, {
                    remove: function (e) {
                        e.target === r && this.destroy()
                    }
                }), this.document = e(r.style ? r.ownerDocument : r.document || r), this.window = e(this.document[0].defaultView || this.document[0].parentWindow)), this._create(), this._trigger("create", null, this._getCreateEventData()), this._init()
            },
            _getCreateOptions: e.noop,
            _getCreateEventData: e.noop,
            _create: e.noop,
            _init: e.noop,
            destroy: function () {
                this._destroy(), this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)), this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName + "-disabled ui-state-disabled"), this.bindings.unbind(this.eventNamespace), this.hoverable.removeClass("ui-state-hover"), this.focusable.removeClass("ui-state-focus")
            },
            _destroy: e.noop,
            widget: function () {
                return this.element
            },
            option: function (n, r) {
                var s, o, u, i = n;
                if (0 === arguments.length) return e.widget.extend({}, this.options);
                if ("string" == typeof n)
                    if (i = {}, s = n.split("."), n = s.shift(), s.length) {
                        for (o = i[n] = e.widget.extend({}, this.options[n]), u = 0; u < s.length - 1; u++) o[s[u]] = o[s[u]] || {}, o = o[s[u]];
                        if (n = s.pop(), r === t) return o[n] === t ? null : o[n];
                        o[n] = r
                    } else {
                        if (r === t) return this.options[n] === t ? null : this.options[n];
                        i[n] = r
                    }
                return this._setOptions(i), this
            },
            _setOptions: function (e) {
                var t;
                for (t in e) this._setOption(t, e[t]);
                return this
            },
            _setOption: function (e, t) {
                return this.options[e] = t, "disabled" === e && (this.widget().toggleClass(this.widgetFullName + "-disabled", !!t), this.hoverable.removeClass("ui-state-hover"), this.focusable.removeClass("ui-state-focus")), this
            },
            enable: function () {
                return this._setOptions({
                    disabled: !1
                })
            },
            disable: function () {
                return this._setOptions({
                    disabled: !0
                })
            },
            _on: function (t, n, r) {
                var i, s = this;
                "boolean" != typeof t && (r = n, n = t, t = !1), r ? (n = i = e(n), this.bindings = this.bindings.add(n)) : (r = n, n = this.element, i = this.widget()), e.each(r, function (r, o) {
                    function u() {
                        return t || s.options.disabled !== !0 && !e(this).hasClass("ui-state-disabled") ? ("string" == typeof o ? s[o] : o).apply(s, arguments) : void 0
                    }
                    "string" != typeof o && (u.guid = o.guid = o.guid || u.guid || e.guid++);
                    var a = r.match(/^(\w+)\s*(.*)$/),
                        f = a[1] + s.eventNamespace,
                        l = a[2];
                    l ? i.delegate(l, f, u) : n.bind(f, u)
                })
            },
            _off: function (e, t) {
                t = (t || "").split(" ").join(this.eventNamespace + " ") + this.eventNamespace, e.unbind(t).undelegate(t)
            },
            _delay: function (e, t) {
                function n() {
                    return ("string" == typeof e ? r[e] : e).apply(r, arguments)
                }
                var r = this;
                return setTimeout(n, t || 0)
            },
            _hoverable: function (t) {
                this.hoverable = this.hoverable.add(t), this._on(t, {
                    mouseenter: function (t) {
                        e(t.currentTarget).addClass("ui-state-hover")
                    },
                    mouseleave: function (t) {
                        e(t.currentTarget).removeClass("ui-state-hover")
                    }
                })
            },
            _focusable: function (t) {
                this.focusable = this.focusable.add(t), this._on(t, {
                    focusin: function (t) {
                        e(t.currentTarget).addClass("ui-state-focus")
                    },
                    focusout: function (t) {
                        e(t.currentTarget).removeClass("ui-state-focus")
                    }
                })
            },
            _trigger: function (t, n, r) {
                var i, s, o = this.options[t];
                if (r = r || {}, n = e.Event(n), n.type = (t === this.widgetEventPrefix ? t : this.widgetEventPrefix + t).toLowerCase(), n.target = this.element[0], s = n.originalEvent, s)
                    for (i in s) i in n || (n[i] = s[i]);
                return this.element.trigger(n, r), !(e.isFunction(o) && o.apply(this.element[0], [n].concat(r)) === !1 || n.isDefaultPrevented())
            }
        }, e.each({
            show: "fadeIn",
            hide: "fadeOut"
        }, function (t, n) {
            e.Widget.prototype["_" + t] = function (r, i, s) {
                "string" == typeof i && (i = {
                    effect: i
                });
                var o, u = i ? i === !0 || "number" == typeof i ? n : i.effect || n : t;
                i = i || {}, "number" == typeof i && (i = {
                    duration: i
                }), o = !e.isEmptyObject(i), i.complete = s, i.delay && r.delay(i.delay), o && e.effects && e.effects.effect[u] ? r[t](i) : u !== t && r[u] ? r[u](i.duration, i.easing, s) : r.queue(function (n) {
                    e(this)[t](), s && s.call(r[0]), n()
                })
            }
        })
    }(e),
    function (e) {
        var n = /[A-Z]/g,
            r = function (e) {
                return "-" + e.toLowerCase()
            };
        e.extend(e.Widget.prototype, {
            _getCreateOptions: function () {
                var t, i, s = this.element[0],
                    o = {};
                if (!e.mobile.getAttribute(s, "defaults"))
                    for (t in this.options) i = e.mobile.getAttribute(s, t.replace(n, r)), null != i && (o[t] = i);
                return o
            }
        }), e.mobile.widget = e.Widget
    }(e),
    function (e, t) {
        e.mobile.widgets = {};
        var n = e.widget,
            r = e.mobile.keepNative;
        e.widget = function (n) {
            return function () {
                var r = n.apply(this, arguments),
                    i = r.prototype.widgetName;
                return r.initSelector = r.prototype.initSelector !== t ? r.prototype.initSelector : ":jqmData(role='" + i + "')", e.mobile.widgets[i] = r, r
            }
        }(e.widget), e.extend(e.widget, n), e.mobile.document.on("create", function (t) {
            e(t.target).enhanceWithin()
        }), e.widget("mobile.page", {
            options: {
                theme: "a",
                domCache: !1,
                keepNativeDefault: e.mobile.keepNative,
                contentTheme: null,
                enhanced: !1
            },
            _createWidget: function () {
                e.Widget.prototype._createWidget.apply(this, arguments), this._trigger("init")
            },
            _create: function () {
                return this._trigger("beforecreate") === !1 ? !1 : (this.options.enhanced || this._enhance(), this._on(this.element, {
                    pagebeforehide: "removeContainerBackground",
                    pagebeforeshow: "_handlePageBeforeShow"
                }), this.element.enhanceWithin(), "dialog" === e.mobile.getAttribute(this.element[0], "role") && e.mobile.dialog && this.element.dialog(), void 0)
            },
            _enhance: function () {
                var n = "data-" + e.mobile.ns,
                    r = this;
                this.options.role && this.element.attr("data-" + e.mobile.ns + "role", this.options.role), this.element.attr("tabindex", "0").addClass("ui-page ui-page-theme-" + this.options.theme), this.element.find("[" + n + "role='content']").each(function () {
                    var i = e(this),
                        s = this.getAttribute(n + "theme") || t;
                    r.options.contentTheme = s || r.options.contentTheme || r.options.dialog && r.options.theme || "dialog" === r.element.jqmData("role") && r.options.theme, i.addClass("ui-content"), r.options.contentTheme && i.addClass("ui-body-" + r.options.contentTheme), i.attr("role", "main").addClass("ui-content")
                })
            },
            bindRemove: function (t) {
                var n = this.element;
                !n.data("mobile-page").options.domCache && n.is(":jqmData(external-page='true')") && n.bind("pagehide.remove", t || function (t, n) {
                    if (!n.samePage) {
                        var r = e(this),
                            i = new e.Event("pageremove");
                        r.trigger(i), i.isDefaultPrevented() || r.removeWithDependents()
                    }
                })
            },
            _setOptions: function (n) {
                n.theme !== t && this.element.removeClass("ui-page-theme-" + this.options.theme).addClass("ui-page-theme-" + n.theme), n.contentTheme !== t && this.element.find("[data-" + e.mobile.ns + "='content']").removeClass("ui-body-" + this.options.contentTheme).addClass("ui-body-" + n.contentTheme)
            },
            _handlePageBeforeShow: function () {
                this.setContainerBackground()
            },
            removeContainerBackground: function () {
                this.element.closest(":mobile-pagecontainer").pagecontainer({
                    theme: "none"
                })
            },
            setContainerBackground: function (e) {
                this.element.parent().pagecontainer({
                    theme: e || this.options.theme
                })
            },
            keepNativeSelector: function () {
                var t = this.options,
                    n = e.trim(t.keepNative || ""),
                    i = e.trim(e.mobile.keepNative),
                    s = e.trim(t.keepNativeDefault),
                    o = r === i ? "" : i,
                    u = "" === o ? s : "";
                return (n ? [n] : []).concat(o ? [o] : []).concat(u ? [u] : []).join(", ")
            }
        })
    }(e),
    function (e, t) {
        e.mobile.Transition = function () {
            this.init.apply(this, arguments)
        }, e.extend(e.mobile.Transition.prototype, {
            toPreClass: " ui-page-pre-in",
            init: function (t, n, r, i) {
                e.extend(this, {
                    name: t,
                    reverse: n,
                    $to: r,
                    $from: i,
                    deferred: new e.Deferred
                })
            },
            cleanFrom: function () {
                this.$from.removeClass(e.mobile.activePageClass + " out in reverse " + this.name).height("")
            },
            beforeDoneIn: function () {},
            beforeDoneOut: function () {},
            beforeStartOut: function () {},
            doneIn: function () {
                this.beforeDoneIn(), this.$to.removeClass("out in reverse " + this.name).height(""), this.toggleViewportClass(), e.mobile.window.scrollTop() !== this.toScroll && this.scrollPage(), this.sequential || this.$to.addClass(e.mobile.activePageClass), this.deferred.resolve(this.name, this.reverse, this.$to, this.$from, !0)
            },
            doneOut: function (e, t, n, r) {
                this.beforeDoneOut(), this.startIn(e, t, n, r)
            },
            hideIn: function (e) {
                this.$to.css("z-index", -10), e.call(this), this.$to.css("z-index", "")
            },
            scrollPage: function () {
                e.event.special.scrollstart.enabled = !1, (e.mobile.hideUrlBar || this.toScroll !== e.mobile.defaultHomeScroll) && t.scrollTo(0, this.toScroll), setTimeout(function () {
                    e.event.special.scrollstart.enabled = !0
                }, 150)
            },
            startIn: function (t, n, r, i) {
                this.hideIn(function () {
                    this.$to.addClass(e.mobile.activePageClass + this.toPreClass), i || e.mobile.focusPage(this.$to), this.$to.height(t + this.toScroll), r || this.scrollPage()
                }), this.$to.removeClass(this.toPreClass).addClass(this.name + " in " + n), r ? this.doneIn() : this.$to.animationComplete(e.proxy(function () {
                    this.doneIn()
                }, this))
            },
            startOut: function (t, n, r) {
                this.beforeStartOut(t, n, r), this.$from.height(t + e.mobile.window.scrollTop()).addClass(this.name + " out" + n)
            },
            toggleViewportClass: function () {
                e.mobile.pageContainer.toggleClass("ui-mobile-viewport-transitioning viewport-" + this.name)
            },
            transition: function () {
                var t, n = this.reverse ? " reverse" : "",
                    r = e.mobile.getScreenHeight(),
                    i = e.mobile.maxTransitionWidth !== !1 && e.mobile.window.width() > e.mobile.maxTransitionWidth;
                return this.toScroll = e.mobile.navigate.history.getActive().lastScroll || e.mobile.defaultHomeScroll, t = !e.support.cssTransitions || !e.support.cssAnimations || i || !this.name || "none" === this.name || Math.max(e.mobile.window.scrollTop(), this.toScroll) > e.mobile.getMaxScrollForTransition(), this.toggleViewportClass(), this.$from && !t ? this.startOut(r, n, t) : this.doneOut(r, n, t, !0), this.deferred.promise()
            }
        })
    }(e, this),
    function (e) {
        e.mobile.SerialTransition = function () {
            this.init.apply(this, arguments)
        }, e.extend(e.mobile.SerialTransition.prototype, e.mobile.Transition.prototype, {
            sequential: !0,
            beforeDoneOut: function () {
                this.$from && this.cleanFrom()
            },
            beforeStartOut: function (t, n, r) {
                this.$from.animationComplete(e.proxy(function () {
                    this.doneOut(t, n, r)
                }, this))
            }
        })
    }(e),
    function (e) {
        e.mobile.ConcurrentTransition = function () {
            this.init.apply(this, arguments)
        }, e.extend(e.mobile.ConcurrentTransition.prototype, e.mobile.Transition.prototype, {
            sequential: !1,
            beforeDoneIn: function () {
                this.$from && this.cleanFrom()
            },
            beforeStartOut: function (e, t, n) {
                this.doneOut(e, t, n)
            }
        })
    }(e),
    function (e) {
        var t = function () {
            return 3 * e.mobile.getScreenHeight()
        };
        e.mobile.transitionHandlers = {
            sequential: e.mobile.SerialTransition,
            simultaneous: e.mobile.ConcurrentTransition
        }, e.mobile.defaultTransitionHandler = e.mobile.transitionHandlers.sequential, e.mobile.transitionFallbacks = {}, e.mobile._maybeDegradeTransition = function (t) {
            return t && !e.support.cssTransform3d && e.mobile.transitionFallbacks[t] && (t = e.mobile.transitionFallbacks[t]), t
        }, e.mobile.getMaxScrollForTransition = e.mobile.getMaxScrollForTransition || t
    }(e),
    function (e, r) {
        e.widget("mobile.pagecontainer", {
            options: {
                theme: "a"
            },
            initSelector: !1,
            _create: function () {
                this.setLastScrollEnabled = !0, this._on(this.window, {
                    navigate: "_disableRecordScroll",
                    scrollstop: "_delayedRecordScroll"
                }), this._on(this.window, {
                    navigate: "_filterNavigateEvents"
                }), this._on({
                    pagechange: "_afterContentChange"
                }), this.window.one("navigate", e.proxy(function () {
                    this.setLastScrollEnabled = !0
                }, this))
            },
            _setOptions: function (e) {
                e.theme !== r && "none" !== e.theme ? this.element.removeClass("ui-overlay-" + this.options.theme).addClass("ui-overlay-" + e.theme) : e.theme !== r && this.element.removeClass("ui-overlay-" + this.options.theme), this._super(e)
            },
            _disableRecordScroll: function () {
                this.setLastScrollEnabled = !1
            },
            _enableRecordScroll: function () {
                this.setLastScrollEnabled = !0
            },
            _afterContentChange: function () {
                this.setLastScrollEnabled = !0, this._off(this.window, "scrollstop"), this._on(this.window, {
                    scrollstop: "_delayedRecordScroll"
                })
            },
            _recordScroll: function () {
                if (this.setLastScrollEnabled) {
                    var t, n, r, e = this._getActiveHistory();
                    e && (t = this._getScroll(), n = this._getMinScroll(), r = this._getDefaultScroll(), e.lastScroll = n > t ? r : t)
                }
            },
            _delayedRecordScroll: function () {
                setTimeout(e.proxy(this, "_recordScroll"), 100)
            },
            _getScroll: function () {
                return this.window.scrollTop()
            },
            _getMinScroll: function () {
                return e.mobile.minScrollBack
            },
            _getDefaultScroll: function () {
                return e.mobile.defaultHomeScroll
            },
            _filterNavigateEvents: function (t, n) {
                var r;
                t.originalEvent && t.originalEvent.isDefaultPrevented() || (r = t.originalEvent.type.indexOf("hashchange") > -1 ? n.state.hash : n.state.url, r || (r = this._getHash()), r && "#" !== r && 0 !== r.indexOf("#" + e.mobile.path.uiStateKey) || (r = location.href), this._handleNavigate(r, n.state))
            },
            _getHash: function () {
                return e.mobile.path.parseLocation().hash
            },
            getActivePage: function () {
                return this.activePage
            },
            _getInitialContent: function () {
                return e.mobile.firstPage
            },
            _getHistory: function () {
                return e.mobile.navigate.history
            },
            _getActiveHistory: function () {
                return e.mobile.navigate.history.getActive()
            },
            _getDocumentBase: function () {
                return e.mobile.path.documentBase
            },
            back: function () {
                this.go(-1)
            },
            forward: function () {
                this.go(1)
            },
            go: function (n) {
                if (e.mobile.hashListeningEnabled) t.history.go(n);
                else {
                    var r = e.mobile.navigate.history.activeIndex,
                        i = r + parseInt(n, 10),
                        s = e.mobile.navigate.history.stack[i].url,
                        o = n >= 1 ? "forward" : "back";
                    e.mobile.navigate.history.activeIndex = i, e.mobile.navigate.history.previousIndex = r, this.change(s, {
                        direction: o,
                        changeHash: !1,
                        fromHashChange: !0
                    })
                }
            },
            _handleDestination: function (t) {
                var n;
                return "string" === e.type(t) && (t = e.mobile.path.stripHash(t)), t && (n = this._getHistory(), t = e.mobile.path.isPath(t) ? t : e.mobile.path.makeUrlAbsolute("#" + t, this._getDocumentBase()), t === e.mobile.path.makeUrlAbsolute("#" + n.initialDst, this._getDocumentBase()) && n.stack.length && n.stack[0].url !== n.initialDst.replace(e.mobile.dialogHashKey, "") && (t = this._getInitialContent())), t || this._getInitialContent()
            },
            _handleDialog: function (t, n) {
                var r, i, s = this.getActivePage();
                return s && !s.hasClass("ui-dialog") ? ("back" === n.direction ? this.back() : this.forward(), !1) : (r = n.pageUrl, i = this._getActiveHistory(), e.extend(t, {
                    role: i.role,
                    transition: i.transition,
                    reverse: "back" === n.direction
                }), r)
            },
            _handleNavigate: function (t, n) {
                var i = e.mobile.path.stripHash(t),
                    s = this._getHistory(),
                    o = 0 === s.stack.length ? "none" : r,
                    u = {
                        changeHash: !1,
                        fromHashChange: !0,
                        reverse: "back" === n.direction
                    };
                e.extend(u, n, {
                    transition: (s.getLast() || {}).transition || o
                }), s.activeIndex > 0 && i.indexOf(e.mobile.dialogHashKey) > -1 && s.initialDst !== i && (i = this._handleDialog(u, n), i === !1) || this._changeContent(this._handleDestination(i), u)
            },
            _changeContent: function (t, n) {
                e.mobile.changePage(t, n)
            },
            _getBase: function () {
                return e.mobile.base
            },
            _getNs: function () {
                return e.mobile.ns
            },
            _enhance: function (e, t) {
                return e.page({
                    role: t
                })
            },
            _include: function (e, t) {
                e.appendTo(this.element), this._enhance(e, t.role), e.page("bindRemove")
            },
            _find: function (t) {
                var i, n = this._createFileUrl(t),
                    r = this._createDataUrl(t),
                    s = this._getInitialContent();
                return i = this.element.children("[data-" + this._getNs() + "url='" + r + "']"), 0 === i.length && r && !e.mobile.path.isPath(r) && (i = this.element.children(e.mobile.path.hashToSelector("#" + r)).attr("data-" + this._getNs() + "url", r).jqmData("url", r)), 0 === i.length && e.mobile.path.isFirstPageUrl(n) && s && s.parent().length && (i = e(s)), i
            },
            _getLoader: function () {
                return e.mobile.loading()
            },
            _showLoading: function (t, n, r, i) {
                this._loadMsg || (this._loadMsg = setTimeout(e.proxy(function () {
                    this._getLoader().loader("show", n, r, i), this._loadMsg = 0
                }, this), t))
            },
            _hideLoading: function () {
                clearTimeout(this._loadMsg), this._loadMsg = 0, this._getLoader().loader("hide")
            },
            _showError: function () {
                this._hideLoading(), this._showLoading(0, e.mobile.pageLoadErrorMessageTheme, e.mobile.pageLoadErrorMessage, !0), setTimeout(e.proxy(this, "_hideLoading"), 1500)
            },
            _parse: function (t, n) {
                var r, i = e("<div></div>");
                return i.get(0).innerHTML = t, r = i.find(":jqmData(role='page'), :jqmData(role='dialog')").first(), r.length || (r = e("<div data-" + this._getNs() + "role='page'>" + (t.split(/<\/?body[^>]*>/gim)[1] || "") + "</div>")), r.attr("data-" + this._getNs() + "url", e.mobile.path.convertUrlToDataUrl(n)).attr("data-" + this._getNs() + "external-page", !0), r
            },
            _setLoadedTitle: function (t, n) {
                var r = n.match(/<title[^>]*>([^<]*)/) && RegExp.$1;
                r && !t.jqmData("title") && (r = e("<div>" + r + "</div>").text(), t.jqmData("title", r))
            },
            _isRewritableBaseTag: function () {
                return e.mobile.dynamicBaseEnabled && !e.support.dynamicBaseTag
            },
            _createDataUrl: function (t) {
                return e.mobile.path.convertUrlToDataUrl(t)
            },
            _createFileUrl: function (t) {
                return e.mobile.path.getFilePath(t)
            },
            _triggerWithDeprecated: function (t, n, r) {
                var i = e.Event("page" + t),
                    s = e.Event(this.widgetName + t);
                return (r || this.element).trigger(i, n), this.element.trigger(s, n), {
                    deprecatedEvent: i,
                    event: s
                }
            },
            _loadSuccess: function (t, n, i, s) {
                var o = this._createFileUrl(t),
                    u = this._createDataUrl(t);
                return e.proxy(function (a, f, l) {
                    var c, h = new RegExp("(<[^>]+\\bdata-" + this._getNs() + "role=[\"']?page[\"']?[^>]*>)"),
                        p = new RegExp("\\bdata-" + this._getNs() + "url=[\"']?([^\"'>]*)[\"']?");
                    h.test(a) && RegExp.$1 && p.test(RegExp.$1) && RegExp.$1 && (o = e.mobile.path.getFilePath(e("<div>" + RegExp.$1 + "</div>").text())), i.prefetch === r && this._getBase().set(o), c = this._parse(a, o), this._setLoadedTitle(c, a), n.xhr = l, n.textStatus = f, n.page = c, n.content = c, this._trigger("load", r, n) && (this._isRewritableBaseTag() && c && this._getBase().rewrite(o, c), this._include(c, i), t.indexOf("&" + e.mobile.subPageUrlKey) > -1 && (c = this.element.children("[data-" + this._getNs() + "url='" + u + "']")), i.showLoadMsg && this._hideLoading(), this.element.trigger("pageload"), s.resolve(t, i, c))
                }, this)
            },
            _loadDefaults: {
                type: "get",
                data: r,
                reloadPage: !1,
                reload: !1,
                role: r,
                showLoadMsg: !1,
                loadMsgDelay: 50
            },
            load: function (t, n) {
                var a, f, l, c, i = n && n.deferred || e.Deferred(),
                    s = e.extend({}, this._loadDefaults, n),
                    o = null,
                    u = e.mobile.path.makeUrlAbsolute(t, this._findBaseWithDefault());
                return s.reload = s.reloadPage, s.data && "get" === s.type && (u = e.mobile.path.addSearchParams(u, s.data), s.data = r), s.data && "post" === s.type && (s.reload = !0), a = this._createFileUrl(u), f = this._createDataUrl(u), o = this._find(u), 0 === o.length && e.mobile.path.isEmbeddedPage(a) && !e.mobile.path.isFirstPageUrl(a) ? (i.reject(u, s), void 0) : (this._getBase().reset(), o.length && !s.reload ? (this._enhance(o, s.role), i.resolve(u, s, o), s.prefetch || this._getBase().set(t), void 0) : (c = {
                    url: t,
                    absUrl: u,
                    dataUrl: f,
                    deferred: i,
                    options: s
                }, l = this._triggerWithDeprecated("beforeload", c), l.deprecatedEvent.isDefaultPrevented() || l.event.isDefaultPrevented() ? void 0 : (s.showLoadMsg && this._showLoading(s.loadMsgDelay), s.prefetch === r && this._getBase().reset(), e.mobile.allowCrossDomainPages || e.mobile.path.isSameDomain(e.mobile.path.documentUrl, u) ? (e.ajax({
                    url: a,
                    type: s.type,
                    data: s.data,
                    contentType: s.contentType,
                    dataType: "html",
                    success: this._loadSuccess(u, c, s, i),
                    error: this._loadError(u, c, s, i)
                }), void 0) : (i.reject(u, s), void 0))))
            },
            _loadError: function (t, n, r, i) {
                return e.proxy(function (s, o, u) {
                    this._getBase().set(e.mobile.path.get()), n.xhr = s, n.textStatus = o, n.errorThrown = u;
                    var a = this._triggerWithDeprecated("loadfailed", n);
                    a.deprecatedEvent.isDefaultPrevented() || a.event.isDefaultPrevented() || (r.showLoadMsg && this._showError(), i.reject(t, r))
                }, this)
            },
            _getTransitionHandler: function (t) {
                return t = e.mobile._maybeDegradeTransition(t), e.mobile.transitionHandlers[t] || e.mobile.defaultTransitionHandler
            },
            _triggerCssTransitionEvents: function (t, n, r) {
                var i = !1;
                r = r || "", n && (t[0] === n[0] && (i = !0), this._triggerWithDeprecated(r + "hide", {
                    nextPage: t,
                    samePage: i
                }, n)), this._triggerWithDeprecated(r + "show", {
                    prevPage: n || e("")
                }, t)
            },
            _cssTransition: function (t, n, r) {
                var u, a, i = r.transition,
                    s = r.reverse,
                    o = r.deferred;
                this._triggerCssTransitionEvents(t, n, "before"), this._hideLoading(), u = this._getTransitionHandler(i), a = new u(i, s, t, n).transition(), a.done(function () {
                    o.resolve.apply(o, arguments)
                }), a.done(e.proxy(function () {
                    this._triggerCssTransitionEvents(t, n)
                }, this))
            },
            _releaseTransitionLock: function () {
                s = !1, i.length > 0 && e.mobile.changePage.apply(null, i.pop())
            },
            _removeActiveLinkClass: function (t) {
                e.mobile.removeActiveLinkClass(t)
            },
            _loadUrl: function (t, n, r) {
                r.target = t, r.deferred = e.Deferred(), this.load(t, r), r.deferred.done(e.proxy(function (e, t, r) {
                    s = !1, t.absUrl = n.absUrl, this.transition(r, n, t)
                }, this)), r.deferred.fail(e.proxy(function () {
                    this._removeActiveLinkClass(!0), this._releaseTransitionLock(), this._triggerWithDeprecated("changefailed", n)
                }, this))
            },
            _triggerPageBeforeChange: function (t, n, r) {
                var i = new e.Event("pagebeforechange");
                return e.extend(n, {
                    toPage: t,
                    options: r
                }), n.absUrl = "string" === e.type(t) ? e.mobile.path.makeUrlAbsolute(t, this._findBaseWithDefault()) : r.absUrl, this.element.trigger(i, n), i.isDefaultPrevented() ? !1 : !0
            },
            change: function (t, n) {
                if (s) return i.unshift(arguments), void 0;
                var r = e.extend({}, e.mobile.changePage.defaults, n),
                    o = {};
                r.fromPage = r.fromPage || this.activePage, this._triggerPageBeforeChange(t, o, r) && (t = o.toPage, "string" === e.type(t) ? (s = !0, this._loadUrl(t, o, r)) : this.transition(t, o, r))
            },
            transition: function (t, o, u) {
                var a, f, l, c, h, p, d, v, m, g, y, b, w, E;
                if (s) return i.unshift([t, u]), void 0;
                if (this._triggerPageBeforeChange(t, o, u) && (E = this._triggerWithDeprecated("beforetransition", o), !E.deprecatedEvent.isDefaultPrevented() && !E.event.isDefaultPrevented())) {
                    if (s = !0, t[0] === e.mobile.firstPage[0] && !u.dataUrl && (u.dataUrl = e.mobile.path.documentUrl.hrefNoHash), a = u.fromPage, f = u.dataUrl && e.mobile.path.convertUrlToDataUrl(u.dataUrl) || t.jqmData("url"), l = f, c = e.mobile.path.getFilePath(f), h = e.mobile.navigate.history.getActive(), p = 0 === e.mobile.navigate.history.activeIndex, d = 0, v = n.title, m = ("dialog" === u.role || "dialog" === t.jqmData("role")) && t.jqmData("dialog") !== !0, a && a[0] === t[0] && !u.allowSamePageTransition) return s = !1, this._triggerWithDeprecated("transition", o), this.element.trigger("pagechange", o), u.fromHashChange && e.mobile.navigate.history.direct({
                        url: f
                    }), void 0;
                    t.page({
                        role: u.role
                    }), u.fromHashChange && (d = "back" === u.direction ? -1 : 1);
                    try {
                        n.activeElement && "body" !== n.activeElement.nodeName.toLowerCase() ? e(n.activeElement).blur() : e("input:focus, textarea:focus, select:focus").blur()
                    } catch (S) {}
                    g = !1, m && h && (h.url && h.url.indexOf(e.mobile.dialogHashKey) > -1 && this.activePage && !this.activePage.hasClass("ui-dialog") && e.mobile.navigate.history.activeIndex > 0 && (u.changeHash = !1, g = !0), f = h.url || "", f += !g && f.indexOf("#") > -1 ? e.mobile.dialogHashKey : "#" + e.mobile.dialogHashKey, 0 === e.mobile.navigate.history.activeIndex && f === e.mobile.navigate.history.initialDst && (f += e.mobile.dialogHashKey)), y = h ? t.jqmData("title") || t.children(":jqmData(role='header')").find(".ui-title").text() : v, !!y && v === n.title && (v = y), t.jqmData("title") || t.jqmData("title", v), u.transition = u.transition || (d && !p ? h.transition : r) || (m ? e.mobile.defaultDialogTransition : e.mobile.defaultPageTransition), !d && g && (e.mobile.navigate.history.getActive().pageUrl = l), f && !u.fromHashChange && (!e.mobile.path.isPath(f) && f.indexOf("#") < 0 && (f = "#" + f), b = {
                        transition: u.transition,
                        title: v,
                        pageUrl: l,
                        role: u.role
                    }, u.changeHash !== !1 && e.mobile.hashListeningEnabled ? e.mobile.navigate(f, b, !0) : t[0] !== e.mobile.firstPage[0] && e.mobile.navigate.history.add(f, b)), n.title = v, e.mobile.activePage = t, this.activePage = t, u.reverse = u.reverse || 0 > d, w = e.Deferred(), this._cssTransition(t, a, {
                        transition: u.transition,
                        reverse: u.reverse,
                        deferred: w
                    }), w.done(e.proxy(function (n, r, i, s, a) {
                        e.mobile.removeActiveLinkClass(), u.duplicateCachedPage && u.duplicateCachedPage.remove(), a || e.mobile.focusPage(t), this._releaseTransitionLock(), this.element.trigger("pagechange", o), this._triggerWithDeprecated("transition", o)
                    }, this))
                }
            },
            _findBaseWithDefault: function () {
                var t = this.activePage && e.mobile.getClosestBaseUrl(this.activePage);
                return t || e.mobile.path.documentBase.hrefNoHash
            }
        }), e.mobile.navreadyDeferred = e.Deferred();
        var i = [],
            s = !1
    }(e),
    function (e, n) {
        function u(e) {
            for (; e && ("string" != typeof e.nodeName || "a" !== e.nodeName.toLowerCase());) e = e.parentNode;
            return e
        }
        var r = e.Deferred(),
            i = e.Deferred(),
            s = e.mobile.path.documentUrl,
            o = null;
        e.mobile.loadPage = function (t, n) {
            var r;
            return n = n || {}, r = n.pageContainer || e.mobile.pageContainer, n.deferred = e.Deferred(), r.pagecontainer("load", t, n), n.deferred.promise()
        }, e.mobile.back = function () {
            var n = t.navigator;
            this.phonegapNavigationEnabled && n && n.app && n.app.backHistory ? n.app.backHistory() : e.mobile.pageContainer.pagecontainer("back")
        }, e.mobile.focusPage = function (e) {
            var t = e.find("[autofocus]"),
                n = e.find(".ui-title:eq(0)");
            return t.length ? (t.focus(), void 0) : (n.length ? n.focus() : e.focus(), void 0)
        }, e.mobile._maybeDegradeTransition = e.mobile._maybeDegradeTransition || function (e) {
            return e
        }, e.mobile.changePage = function (t, n) {
            e.mobile.pageContainer.pagecontainer("change", t, n)
        }, e.mobile.changePage.defaults = {
            transition: n,
            reverse: !1,
            changeHash: !0,
            fromHashChange: !1,
            role: n,
            duplicateCachedPage: n,
            pageContainer: n,
            showLoadMsg: !0,
            dataUrl: n,
            fromPage: n,
            allowSamePageTransition: !1
        }, e.mobile._registerInternalEvents = function () {
            var r = function (t, n) {
                var r, u, a, f, i = !0;
                return !e.mobile.ajaxEnabled || t.is(":jqmData(ajax='false')") || !t.jqmHijackable().length || t.attr("target") ? !1 : (r = o && o.attr("formaction") || t.attr("action"), f = (t.attr("method") || "get").toLowerCase(), r || (r = e.mobile.getClosestBaseUrl(t), "get" === f && (r = e.mobile.path.parseUrl(r).hrefNoSearch), r === e.mobile.path.documentBase.hrefNoHash && (r = s.hrefNoSearch)), r = e.mobile.path.makeUrlAbsolute(r, e.mobile.getClosestBaseUrl(t)), e.mobile.path.isExternal(r) && !e.mobile.path.isPermittedCrossDomainRequest(s, r) ? !1 : (n || (u = t.serializeArray(), o && o[0].form === t[0] && (a = o.attr("name"), a && (e.each(u, function (e, t) {
                    return t.name === a ? (a = "", !1) : void 0
                }), a && u.push({
                    name: a,
                    value: o.attr("value")
                }))), i = {
                    url: r,
                    options: {
                        type: f,
                        data: e.param(u),
                        transition: t.jqmData("transition"),
                        reverse: "reverse" === t.jqmData("direction"),
                        reloadPage: !0
                    }
                }), i))
            };
            e.mobile.document.delegate("form", "submit", function (t) {
                var n;
                t.isDefaultPrevented() || (n = r(e(this)), n && (e.mobile.changePage(n.url, n.options), t.preventDefault()))
            }), e.mobile.document.bind("vclick", function (t) {
                var n, i, s = t.target,
                    a = !1;
                if (!(t.which > 1) && e.mobile.linkBindingEnabled) {
                    if (o = e(s), e.data(s, "mobile-button")) {
                        if (!r(e(s).closest("form"), !0)) return;
                        s.parentNode && (s = s.parentNode)
                    } else {
                        if (s = u(s), !s || "#" === e.mobile.path.parseUrl(s.getAttribute("href") || "#").hash) return;
                        if (!e(s).jqmHijackable().length) return
                    }~
                    s.className.indexOf("ui-link-inherit") ? s.parentNode && (i = e.data(s.parentNode, "buttonElements")) : i = e.data(s, "buttonElements"), i ? s = i.outer : a = !0, n = e(s), a && (n = n.closest(".ui-btn")), n.length > 0 && !n.hasClass("ui-state-disabled") && (e.mobile.removeActiveLinkClass(!0), e.mobile.activeClickedLink = n, e.mobile.activeClickedLink.addClass(e.mobile.activeBtnClass))
                }
            }), e.mobile.document.bind("click", function (r) {
                if (e.mobile.linkBindingEnabled && !r.isDefaultPrevented()) {
                    var f, l, c, h, p, d, v, i = u(r.target),
                        o = e(i),
                        a = function () {
                            t.setTimeout(function () {
                                e.mobile.removeActiveLinkClass(!0)
                            }, 200)
                        };
                    if (e.mobile.activeClickedLink && e.mobile.activeClickedLink[0] === r.target.parentNode && a(), i && !(r.which > 1) && o.jqmHijackable().length) {
                        if (o.is(":jqmData(rel='back')")) return e.mobile.back(), !1;
                        if (f = e.mobile.getClosestBaseUrl(o), l = e.mobile.path.makeUrlAbsolute(o.attr("href") || "#", f), !e.mobile.ajaxEnabled && !e.mobile.path.isEmbeddedPage(l)) return a(), void 0;
                        if (-1 !== l.search("#")) {
                            if (l = l.replace(/[^#]*#/, ""), !l) return r.preventDefault(), void 0;
                            l = e.mobile.path.isPath(l) ? e.mobile.path.makeUrlAbsolute(l, f) : e.mobile.path.makeUrlAbsolute("#" + l, s.hrefNoHash)
                        }
                        return c = o.is("[rel='external']") || o.is(":jqmData(ajax='false')") || o.is("[target]"), (h = c || e.mobile.path.isExternal(l) && !e.mobile.path.isPermittedCrossDomainRequest(s, l)) ? (a(), void 0) : (p = o.jqmData("transition"), d = "reverse" === o.jqmData("direction") || o.jqmData("back"), v = o.attr("data-" + e.mobile.ns + "rel") || n, e.mobile.changePage(l, {
                            transition: p,
                            reverse: d,
                            role: v,
                            link: o
                        }), r.preventDefault(), void 0)
                    }
                }
            }), e.mobile.document.delegate(".ui-page", "pageshow.prefetch", function () {
                var t = [];
                e(this).find("a:jqmData(prefetch)").each(function () {
                    var n = e(this),
                        r = n.attr("href");
                    r && -1 === e.inArray(r, t) && (t.push(r), e.mobile.loadPage(r, {
                        role: n.attr("data-" + e.mobile.ns + "rel"),
                        prefetch: !0
                    }))
                })
            }), e.mobile.pageContainer.pagecontainer(), e.mobile.document.bind("pageshow", function () {
                i ? i.done(e.mobile.resetActivePageHeight) : e.mobile.resetActivePageHeight()
            }), e.mobile.window.bind("throttledresize", e.mobile.resetActivePageHeight)
        }, e(function () {
            r.resolve()
        }), e.mobile.window.load(function () {
            i.resolve(), i = null
        }), e.when(r, e.mobile.navreadyDeferred).done(function () {
            e.mobile._registerInternalEvents()
        })
    }(e),
    function (e) {
        var t = e("meta[name=viewport]"),
            n = t.attr("content"),
            r = n + ",maximum-scale=1, user-scalable=no",
            i = n + ",maximum-scale=10, user-scalable=yes",
            s = /(user-scalable[\s]*=[\s]*no)|(maximum-scale[\s]*=[\s]*1)[$,\s]/.test(n);
        e.mobile.zoom = e.extend({}, {
            enabled: !s,
            locked: !1,
            disable: function (n) {
                !s && !e.mobile.zoom.locked && (t.attr("content", r), e.mobile.zoom.enabled = !1, e.mobile.zoom.locked = n || !1)
            },
            enable: function (n) {
                !s && (!e.mobile.zoom.locked || n === !0) && (t.attr("content", i), e.mobile.zoom.enabled = !0, e.mobile.zoom.locked = !1)
            },
            restore: function () {
                s || (t.attr("content", n), e.mobile.zoom.enabled = !0)
            }
        })
    }(e),
    function (e) {
        e.mobile.behaviors.addFirstLastClasses = {
            _getVisibles: function (e, t) {
                var n;
                return t ? n = e.not(".ui-screen-hidden") : (n = e.filter(":visible"), 0 === n.length && (n = e.not(".ui-screen-hidden"))), n
            },
            _addFirstLastClasses: function (e, t, n) {
                e.removeClass("ui-first-child ui-last-child"), t.eq(0).addClass("ui-first-child").end().last().addClass("ui-last-child"), n || this.element.trigger("updatelayout")
            },
            _removeFirstLastClasses: function (e) {
                e.removeClass("ui-first-child ui-last-child")
            }
        }
    }(e),
    function (e, t) {
        var n = /([A-Z])/g,
            r = function (e) {
                return "ui-btn-icon-" + (null === e ? "left" : e)
            };
        e.widget("mobile.collapsible", {
            options: {
                enhanced: !1,
                expandCueText: null,
                collapseCueText: null,
                collapsed: !0,
                heading: "h1,h2,h3,h4,h5,h6,legend",
                collapsedIcon: null,
                expandedIcon: null,
                iconpos: null,
                theme: null,
                contentTheme: null,
                inset: null,
                corners: null,
                mini: null
            },
            _create: function () {
                var t = this.element,
                    n = {
                        accordion: t.closest(":jqmData(role='collapsible-set'),:jqmData(role='collapsibleset')" + (e.mobile.collapsibleset ? ", :mobile-collapsibleset" : "")).addClass("ui-collapsible-set")
                    };
                this._ui = n, this._renderedOptions = this._getOptions(this.options), this.options.enhanced ? (n.heading = e(".ui-collapsible-heading", this.element[0]), n.content = n.heading.next(), n.anchor = e("a", n.heading[0]).first(), n.status = n.anchor.children(".ui-collapsible-heading-status")) : this._enhance(t, n), this._on(n.heading, {
                    tap: function () {
                        n.heading.find("a").first().addClass(e.mobile.activeBtnClass)
                    },
                    click: function (e) {
                        this._handleExpandCollapse(!n.heading.hasClass("ui-collapsible-heading-collapsed")), e.preventDefault(), e.stopPropagation()
                    }
                })
            },
            _getOptions: function (t) {
                var r, i = this._ui.accordion,
                    s = this._ui.accordionWidget;
                t = e.extend({}, t), i.length && !s && (this._ui.accordionWidget = s = i.data("mobile-collapsibleset"));
                for (r in t) t[r] = null != t[r] ? t[r] : s ? s.options[r] : i.length ? e.mobile.getAttribute(i[0], r.replace(n, "-$1").toLowerCase()) : null, null == t[r] && (t[r] = e.mobile.collapsible.defaults[r]);
                return t
            },
            _themeClassFromOption: function (e, t) {
                return t ? "none" === t ? "" : e + t : ""
            },
            _enhance: function (t, n) {
                var i, s = this._renderedOptions,
                    o = this._themeClassFromOption("ui-body-", s.contentTheme);
                return t.addClass("ui-collapsible " + (s.inset ? "ui-collapsible-inset " : "") + (s.inset && s.corners ? "ui-corner-all " : "") + (o ? "ui-collapsible-themed-content " : "")), n.originalHeading = t.children(this.options.heading).first(), n.content = t.wrapInner("<div class='ui-collapsible-content " + o + "'></div>").children(".ui-collapsible-content"), n.heading = n.originalHeading, n.heading.is("legend") && (n.heading = e("<div role='heading'>" + n.heading.html() + "</div>"), n.placeholder = e("<div><!-- placeholder for legend --></div>").insertBefore(n.originalHeading), n.originalHeading.remove()), i = s.collapsed ? s.collapsedIcon ? "ui-icon-" + s.collapsedIcon : "" : s.expandedIcon ? "ui-icon-" + s.expandedIcon : "", n.status = e("<span class='ui-collapsible-heading-status'></span>"), n.anchor = n.heading.detach().addClass("ui-collapsible-heading").append(n.status).wrapInner("<a href='#' class='ui-collapsible-heading-toggle'></a>").find("a").first().addClass("ui-btn " + (i ? i + " " : "") + (i ? r(s.iconpos) + " " : "") + this._themeClassFromOption("ui-btn-", s.theme) + " " + (s.mini ? "ui-mini " : "")), n.heading.insertBefore(n.content), this._handleExpandCollapse(this.options.collapsed), n
            },
            refresh: function () {
                this._applyOptions(this.options), this._renderedOptions = this._getOptions(this.options)
            },
            _applyOptions: function (e) {
                var n, i, s, o, u, a = this.element,
                    f = this._renderedOptions,
                    l = this._ui,
                    c = l.anchor,
                    h = l.status,
                    p = this._getOptions(e);
                e.collapsed !== t && this._handleExpandCollapse(e.collapsed), n = a.hasClass("ui-collapsible-collapsed"), n ? p.expandCueText !== t && h.text(p.expandCueText) : p.collapseCueText !== t && h.text(p.collapseCueText), u = p.collapsedIcon !== t ? p.collapsedIcon !== !1 : f.collapsedIcon !== !1, (p.iconpos !== t || p.collapsedIcon !== t || p.expandedIcon !== t) && (c.removeClass([r(f.iconpos)].concat(f.expandedIcon ? ["ui-icon-" + f.expandedIcon] : []).concat(f.collapsedIcon ? ["ui-icon-" + f.collapsedIcon] : []).join(" ")), u && c.addClass([r(p.iconpos !== t ? p.iconpos : f.iconpos)].concat(n ? ["ui-icon-" + (p.collapsedIcon !== t ? p.collapsedIcon : f.collapsedIcon)] : ["ui-icon-" + (p.expandedIcon !== t ? p.expandedIcon : f.expandedIcon)]).join(" "))), p.theme !== t && (s = this._themeClassFromOption("ui-btn-", f.theme), i = this._themeClassFromOption("ui-btn-", p.theme), c.removeClass(s).addClass(i)), p.contentTheme !== t && (s = this._themeClassFromOption("ui-body-", f.contentTheme), i = this._themeClassFromOption("ui-body-", p.contentTheme), l.content.removeClass(s).addClass(i)), p.inset !== t && (a.toggleClass("ui-collapsible-inset", p.inset), o = !(!p.inset || !p.corners && !f.corners)), p.corners !== t && (o = !(!p.corners || !p.inset && !f.inset)), o !== t && a.toggleClass("ui-corner-all", o), p.mini !== t && c.toggleClass("ui-mini", p.mini)
            },
            _setOptions: function (e) {
                this._applyOptions(e), this._super(e), this._renderedOptions = this._getOptions(this.options)
            },
            _handleExpandCollapse: function (t) {
                var n = this._renderedOptions,
                    r = this._ui;
                r.status.text(t ? n.expandCueText : n.collapseCueText), r.heading.toggleClass("ui-collapsible-heading-collapsed", t).find("a").first().toggleClass("ui-icon-" + n.expandedIcon, !t).toggleClass("ui-icon-" + n.collapsedIcon, t || n.expandedIcon === n.collapsedIcon).removeClass(e.mobile.activeBtnClass), this.element.toggleClass("ui-collapsible-collapsed", t), r.content.toggleClass("ui-collapsible-content-collapsed", t).attr("aria-hidden", t).trigger("updatelayout"), this.options.collapsed = t, this._trigger(t ? "collapse" : "expand")
            },
            expand: function () {
                this._handleExpandCollapse(!1)
            },
            collapse: function () {
                this._handleExpandCollapse(!0)
            },
            _destroy: function () {
                var e = this._ui,
                    t = this.options;
                t.enhanced || (e.placeholder ? (e.originalHeading.insertBefore(e.placeholder), e.placeholder.remove(), e.heading.remove()) : (e.status.remove(), e.heading.removeClass("ui-collapsible-heading ui-collapsible-heading-collapsed").children().contents().unwrap()), e.anchor.contents().unwrap(), e.content.contents().unwrap(), this.element.removeClass("ui-collapsible ui-collapsible-collapsed ui-collapsible-themed-content ui-collapsible-inset ui-corner-all"))
            }
        }), e.mobile.collapsible.defaults = {
            expandCueText: " click to expand contents",
            collapseCueText: " click to collapse contents",
            collapsedIcon: "plus",
            contentTheme: "inherit",
            expandedIcon: "minus",
            iconpos: "left",
            inset: !0,
            corners: !0,
            theme: "inherit",
            mini: !1
        }
    }(e),
    function (e, t) {
        var n = ":mobile-collapsible, " + e.mobile.collapsible.initSelector;
        e.widget("mobile.collapsibleset", e.extend({
            initSelector: ":jqmData(role='collapsible-set'),:jqmData(role='collapsibleset')",
            options: e.extend({
                enhanced: !1
            }, e.mobile.collapsible.defaults),
            _handleCollapsibleExpand: function (t) {
                var n = e(t.target).closest(".ui-collapsible");
                n.parent().is(":mobile-collapsibleset, :jqmData(role='collapsible-set')") && n.siblings(".ui-collapsible:not(.ui-collapsible-collapsed)").collapsible("collapse")
            },
            _create: function () {
                var t = this.element,
                    n = this.options;
                e.extend(this, {
                    _classes: ""
                }), n.enhanced || (t.addClass("ui-collapsible-set " + this._themeClassFromOption("ui-group-theme-", n.theme) + " " + (n.corners && n.inset ? "ui-corner-all " : "")), this.element.find(e.mobile.collapsible.initSelector).collapsible()), this._on(t, {
                    collapsibleexpand: "_handleCollapsibleExpand"
                })
            },
            _themeClassFromOption: function (e, t) {
                return t ? "none" === t ? "" : e + t : ""
            },
            _init: function () {
                this._refresh(!0), this.element.children(n).filter(":jqmData(collapsed='false')").collapsible("expand")
            },
            _setOptions: function (e) {
                var n, r, i = this.element,
                    s = this._themeClassFromOption("ui-group-theme-", e.theme);
                return s && i.removeClass(this._themeClassFromOption("ui-group-theme-", this.options.theme)).addClass(s), e.inset !== t && (r = !(!e.inset || !e.corners && !this.options.corners)), e.corners !== t && (r = !(!e.corners || !e.inset && !this.options.inset)), r !== t && i.toggleClass("ui-corner-all", r), n = this._super(e), this.element.children(":mobile-collapsible").collapsible("refresh"), n
            },
            _destroy: function () {
                var e = this.element;
                this._removeFirstLastClasses(e.children(n)), e.removeClass("ui-collapsible-set ui-corner-all " + this._themeClassFromOption("ui-group-theme-", this.options.theme)).children(":mobile-collapsible").collapsible("destroy")
            },
            _refresh: function (t) {
                var r = this.element.children(n);
                this.element.find(e.mobile.collapsible.initSelector).not(".ui-collapsible").collapsible(), this._addFirstLastClasses(r, this._getVisibles(r, t), t)
            },
            refresh: function () {
                this._refresh(!1)
            }
        }, e.mobile.behaviors.addFirstLastClasses))
    }(e),
    function (e, t) {
        e.widget("mobile.controlgroup", e.extend({
            options: {
                enhanced: !1,
                theme: null,
                shadow: !1,
                corners: !0,
                excludeInvisible: !0,
                type: "vertical",
                mini: !1
            },
            _create: function () {
                var t = this.element,
                    n = this.options;
                e.fn.buttonMarkup && this.element.find(e.fn.buttonMarkup.initSelector).buttonMarkup(), e.each(this._childWidgets, e.proxy(function (t, n) {
                    e.mobile[n] && this.element.find(e.mobile[n].initSelector).not(e.mobile.page.prototype.keepNativeSelector())[n]()
                }, this)), e.extend(this, {
                    _ui: null,
                    _initialRefresh: !0
                }), this._ui = n.enhanced ? {
                    groupLegend: t.children(".ui-controlgroup-label").children(),
                    childWrapper: t.children(".ui-controlgroup-controls")
                } : this._enhance()
            },
            _childWidgets: ["checkboxradio", "selectmenu", "button"],
            _themeClassFromOption: function (e) {
                return e ? "none" === e ? "" : "ui-group-theme-" + e : ""
            },
            _enhance: function () {
                var t = this.element,
                    n = this.options,
                    r = {
                        groupLegend: t.children("legend"),
                        childWrapper: t.addClass("ui-controlgroup ui-controlgroup-" + ("horizontal" === n.type ? "horizontal" : "vertical") + " " + this._themeClassFromOption(n.theme) + " " + (n.corners ? "ui-corner-all " : "") + (n.mini ? "ui-mini " : "")).wrapInner("<div class='ui-controlgroup-controls " + (n.shadow === !0 ? "ui-shadow" : "") + "'></div>").children()
                    };
                return r.groupLegend.length > 0 && e("<div role='heading' class='ui-controlgroup-label'></div>").append(r.groupLegend).prependTo(t), r
            },
            _init: function () {
                this.refresh()
            },
            _setOptions: function (e) {
                var n, r, i = this.element;
                return e.type !== t && (i.removeClass("ui-controlgroup-horizontal ui-controlgroup-vertical").addClass("ui-controlgroup-" + ("horizontal" === e.type ? "horizontal" : "vertical")), n = !0), e.theme !== t && i.removeClass(this._themeClassFromOption(this.options.theme)).addClass(this._themeClassFromOption(e.theme)), e.corners !== t && i.toggleClass("ui-corner-all", e.corners), e.mini !== t && i.toggleClass("ui-mini", e.mini), e.shadow !== t && this._ui.childWrapper.toggleClass("ui-shadow", e.shadow), e.excludeInvisible !== t && (this.options.excludeInvisible = e.excludeInvisible, n = !0), r = this._super(e), n && this.refresh(), r
            },
            container: function () {
                return this._ui.childWrapper
            },
            refresh: function () {
                var t = this.container(),
                    n = t.find(".ui-btn").not(".ui-slider-handle"),
                    r = this._initialRefresh;
                e.mobile.checkboxradio && t.find(":mobile-checkboxradio").checkboxradio("refresh"), this._addFirstLastClasses(n, this.options.excludeInvisible ? this._getVisibles(n, r) : n, r), this._initialRefresh = !1
            },
            _destroy: function () {
                var e, t, n = this.options;
                return n.enhanced ? this : (e = this._ui, t = this.element.removeClass("ui-controlgroup ui-controlgroup-horizontal ui-controlgroup-vertical ui-corner-all ui-mini " + this._themeClassFromOption(n.theme)).find(".ui-btn").not(".ui-slider-handle"), this._removeFirstLastClasses(t), e.groupLegend.unwrap(), e.childWrapper.children().unwrap(), void 0)
            }
        }, e.mobile.behaviors.addFirstLastClasses))
    }(e),
    function (e, t, n) {
        e.widget("mobile.dialog", {
            options: {
                closeBtn: "left",
                closeBtnText: "Close",
                overlayTheme: "a",
                corners: !0
            },
            _handlePageBeforeShow: function () {
                this._isCloseable = !0, this.options.overlayTheme && this.element.page("removeContainerBackground").page("setContainerBackground", this.options.overlayTheme)
            },
            _handlePageBeforeHide: function () {
                this._isCloseable = !1
            },
            _handleVClickSubmit: function (t) {
                var n, r = e(t.target).closest("vclick" === t.type ? "a" : "form");
                r.length && !r.jqmData("transition") && (n = {}, n["data-" + e.mobile.ns + "transition"] = (e.mobile.navigate.history.getActive() || {}).transition || e.mobile.defaultDialogTransition, n["data-" + e.mobile.ns + "direction"] = "reverse", r.attr(n))
            },
            _create: function () {
                var t = this.element,
                    n = this.options;
                t.addClass("ui-dialog").wrapInner(e("<div/>", {
                    role: "dialog",
                    "class": "ui-dialog-contain ui-overlay-shadow" + (n.corners ? " ui-corner-all" : "")
                })), e.extend(this, {
                    _isCloseable: !1,
                    _inner: t.children(),
                    _headerCloseButton: null
                }), this._on(t, {
                    vclick: "_handleVClickSubmit",
                    submit: "_handleVClickSubmit",
                    pagebeforeshow: "_handlePageBeforeShow",
                    pagebeforehide: "_handlePageBeforeHide"
                }), this._setCloseBtn(n.closeBtn)
            },
            _setOptions: function (t) {
                var r, i, s = this.options;
                t.corners !== n && this._inner.toggleClass("ui-corner-all", !!t.corners), t.overlayTheme !== n && e.mobile.activePage[0] === this.element[0] && (s.overlayTheme = t.overlayTheme, this._handlePageBeforeShow()), t.closeBtnText !== n && (r = s.closeBtn, i = t.closeBtnText), t.closeBtn !== n && (r = t.closeBtn), r && this._setCloseBtn(r, i), this._super(t)
            },
            _setCloseBtn: function (t, n) {
                var r, i = this._headerCloseButton;
                t = "left" === t ? "left" : "right" === t ? "right" : "none", "none" === t ? i && (i.remove(), i = null) : i ? (i.removeClass("ui-btn-left ui-btn-right").addClass("ui-btn-" + t), n && i.text(n)) : (r = this._inner.find(":jqmData(role='header')").first(), i = e("<a></a>", {
                    role: "button",
                    href: "#",
                    "class": "ui-btn ui-corner-all ui-icon-delete ui-btn-icon-notext ui-btn-" + t
                }).text(n || this.options.closeBtnText || "").prependTo(r), this._on(i, {
                    click: "close"
                })), this._headerCloseButton = i
            },
            close: function () {
                var t = e.mobile.navigate.history;
                this._isCloseable && (this._isCloseable = !1, e.mobile.hashListeningEnabled && t.activeIndex > 0 ? e.mobile.back() : e.mobile.pageContainer.pagecontainer("back"))
            }
        })
    }(e, this),
    function (e, n) {
        var r = function (t, n) {
            return -1 === ("" + (e.mobile.getAttribute(this, "filtertext") || e(this).text())).toLowerCase().indexOf(n)
        };
        e.widget("mobile.filterable", {
            initSelector: ":jqmData(filter='true')",
            options: {
                filterReveal: !1,
                filterCallback: r,
                enhanced: !1,
                input: null,
                children: "> li, > option, > optgroup option, > tbody tr, > .ui-controlgroup-controls > .ui-btn, > .ui-controlgroup-controls > .ui-checkbox, > .ui-controlgroup-controls > .ui-radio"
            },
            _create: function () {
                var t = this.options;
                e.extend(this, {
                    _search: null,
                    _timer: 0
                }), this._setInput(t.input), t.enhanced || this._filterItems((this._search && this._search.val() || "").toLowerCase())
            },
            _onKeyUp: function () {
                var n, r, i = this._search;
                if (i) {
                    if (n = i.val().toLowerCase(), r = e.mobile.getAttribute(i[0], "lastval") + "", r && r === n) return;
                    this._timer && (t.clearTimeout(this._timer), this._timer = 0), this._timer = this._delay(function () {
                        this._trigger("beforefilter", null, {
                            input: i
                        }), i[0].setAttribute("data-" + e.mobile.ns + "lastval", n), this._filterItems(n), this._timer = 0
                    }, 250)
                }
            },
            _getFilterableItems: function () {
                var t = this.element,
                    n = this.options.children,
                    r = n ? e.isFunction(n) ? n() : n.nodeName ? e(n) : n.jquery ? n : this.element.find(n) : {
                        length: 0
                    };
                return 0 === r.length && (r = t.children()), r
            },
            _filterItems: function (t) {
                var n, i, s, o, u = [],
                    a = [],
                    f = this.options,
                    l = this._getFilterableItems();
                if (null != t)
                    for (i = f.filterCallback || r, s = l.length, n = 0; s > n; n++) o = i.call(l[n], n, t) ? a : u, o.push(l[n]);
                0 === a.length ? l[f.filterReveal ? "addClass" : "removeClass"]("ui-screen-hidden") : (e(a).addClass("ui-screen-hidden"), e(u).removeClass("ui-screen-hidden")), this._refreshChildWidget(), this._trigger("filter", null, {
                    items: l
                })
            },
            _refreshChildWidget: function () {
                var t, n, r = ["collapsibleset", "selectmenu", "controlgroup", "listview"];
                for (n = r.length - 1; n > -1; n--) t = r[n], e.mobile[t] && (t = this.element.data("mobile-" + t), t && e.isFunction(t.refresh) && t.refresh())
            },
            _setInput: function (n) {
                var r = this._search;
                this._timer && (t.clearTimeout(this._timer), this._timer = 0), r && (this._off(r, "keyup change input"), r = null), n && (r = n.jquery ? n : n.nodeName ? e(n) : this.document.find(n), this._on(r, {
                    keyup: "_onKeyUp",
                    change: "_onKeyUp",
                    input: "_onKeyUp"
                })), this._search = r
            },
            _setOptions: function (e) {
                var t = e.filterReveal !== n || e.filterCallback !== n || e.children !== n;
                this._super(e), e.input !== n && (this._setInput(e.input), t = !0), t && this.refresh()
            },
            _destroy: function () {
                var e = this.options,
                    t = this._getFilterableItems();
                e.enhanced ? t.toggleClass("ui-screen-hidden", e.filterReveal) : t.removeClass("ui-screen-hidden")
            },
            refresh: function () {
                this._timer && (t.clearTimeout(this._timer), this._timer = 0), this._filterItems((this._search && this._search.val() || "").toLowerCase())
            }
        })
    }(e),
    function (e, t) {
        var n = function (e, t) {
                return function (n) {
                    t.call(this, n), e._syncTextInputOptions(n)
                }
            },
            r = /(^|\s)ui-li-divider(\s|$)/,
            i = e.mobile.filterable.prototype.options.filterCallback;
        e.mobile.filterable.prototype.options.filterCallback = function (e, t) {
            return !this.className.match(r) && i.call(this, e, t)
        }, e.widget("mobile.filterable", e.mobile.filterable, {
            options: {
                filterPlaceholder: "Filter items...",
                filterTheme: null
            },
            _create: function () {
                var t, n, r = this.element,
                    i = ["collapsibleset", "selectmenu", "controlgroup", "listview"],
                    s = {};
                for (this._super(), e.extend(this, {
                    _widget: null
                }), t = i.length - 1; t > -1; t--)
                    if (n = i[t], e.mobile[n]) {
                        if (this._setWidget(r.data("mobile-" + n))) break;
                        s[n + "create"] = "_handleCreate"
                    }
                this._widget || this._on(r, s)
            },
            _handleCreate: function (e) {
                this._setWidget(this.element.data("mobile-" + e.type.substring(0, e.type.length - 6)))
            },
            _trigger: function (e, t, n) {
                this._widget && "mobile-listview" === this._widget.widgetFullName && "beforefilter" === e && this._widget._trigger("beforefilter", t, n), this._super(e, t, n)
            },
            _setWidget: function (e) {
                return !this._widget && e && (this._widget = e, this._widget._setOptions = n(this, this._widget._setOptions)), !this._widget || (this._syncTextInputOptions(this._widget.options), "listview" === this._widget.widgetName && (this._widget.options.hideDividers = !0, this._widget.element.listview("refresh"))), !!this._widget
            },
            _isSearchInternal: function () {
                return this._search && this._search.jqmData("ui-filterable-" + this.uuid + "-internal")
            },
            _setInput: function (t) {
                var n = this.options,
                    r = !0,
                    i = {};
                if (!t) {
                    if (this._isSearchInternal()) return;
                    r = !1, t = e("<input data-" + e.mobile.ns + "type='search' placeholder='" + n.filterPlaceholder + "'></input>").jqmData("ui-filterable-" + this.uuid + "-internal", !0), e("<form class='ui-filterable'></form>").append(t).submit(function (e) {
                        e.preventDefault(), t.blur()
                    }).insertBefore(this.element), e.mobile.textinput && (null != this.options.filterTheme && (i.theme = n.filterTheme), t.textinput(i))
                }
                this._super(t), this._isSearchInternal() && r && this._search.attr("placeholder", this.options.filterPlaceholder)
            },
            _setOptions: function (n) {
                var r = this._super(n);
                return n.filterPlaceholder !== t && this._isSearchInternal() && this._search.attr("placeholder", n.filterPlaceholder), n.filterTheme !== t && this._search && e.mobile.textinput && this._search.textinput("option", "theme", n.filterTheme), r
            },
            _destroy: function () {
                this._isSearchInternal() && this._search.remove(), this._super()
            },
            _syncTextInputOptions: function (n) {
                var r, i = {};
                if (this._isSearchInternal() && e.mobile.textinput) {
                    for (r in e.mobile.textinput.prototype.options) n[r] !== t && (i[r] = "theme" === r && null != this.options.filterTheme ? this.options.filterTheme : n[r]);
                    this._search.textinput("option", i)
                }
            }
        })
    }(e),
    function (e, t) {
        e.widget("mobile.toolbar", {
            initSelector: ":jqmData(role='footer'), :jqmData(role='header')",
            options: {
                theme: null,
                addBackBtn: !1,
                backBtnTheme: null,
                backBtnText: "Back"
            },
            _create: function () {
                var t, n, r = this.element.is(":jqmData(role='header')") ? "header" : "footer",
                    i = this.element.closest(".ui-page");
                0 === i.length && (i = !1, this._on(this.document, {
                    pageshow: "refresh"
                })), e.extend(this, {
                    role: r,
                    page: i,
                    leftbtn: t,
                    rightbtn: n
                }), this.element.attr("role", "header" === r ? "banner" : "contentinfo").addClass("ui-" + r), this.refresh(), this._setOptions(this.options)
            },
            _setOptions: function (n) {
                if (n.addBackBtn !== t && (this.options.addBackBtn && "header" === this.role && e(".ui-page").length > 1 && this.page[0].getAttribute("data-" + e.mobile.ns + "url") !== e.mobile.path.stripHash(location.hash) && !this.leftbtn ? this._addBackButton() : this.element.find(".ui-toolbar-back-btn").remove()), null != n.backBtnTheme && this.element.find(".ui-toolbar-back-btn").addClass("ui-btn ui-btn-" + n.backBtnTheme), n.backBtnText !== t && this.element.find(".ui-toolbar-back-btn .ui-btn-text").text(n.backBtnText), n.theme !== t) {
                    var r = this.options.theme ? this.options.theme : "inherit",
                        i = n.theme ? n.theme : "inherit";
                    this.element.removeClass("ui-bar-" + r).addClass("ui-bar-" + i)
                }
                this._super(n)
            },
            refresh: function () {
                "header" === this.role && this._addHeaderButtonClasses(), this.page || (this._setRelative(), "footer" === this.role && this.element.appendTo("body")), this._addHeadingClasses(), this._btnMarkup()
            },
            _setRelative: function () {
                e("[data-" + e.mobile.ns + "role='page']").css({
                    position: "relative"
                })
            },
            _btnMarkup: function () {
                this.element.children("a").filter(":not([data-" + e.mobile.ns + "role='none'])").attr("data-" + e.mobile.ns + "role", "button"), this.element.trigger("create")
            },
            _addHeaderButtonClasses: function () {
                var e = this.element.children("a, button");
                this.leftbtn = e.hasClass("ui-btn-left"), this.rightbtn = e.hasClass("ui-btn-right"), this.leftbtn = this.leftbtn || e.eq(0).not(".ui-btn-right").addClass("ui-btn-left").length, this.rightbtn = this.rightbtn || e.eq(1).addClass("ui-btn-right").length
            },
            _addBackButton: function () {
                var t = this.options,
                    n = t.backBtnTheme || t.theme;
                e("<a role='button' href='javascript:void(0);' class='ui-btn ui-corner-all ui-shadow ui-btn-left " + (n ? "ui-btn-" + n + " " : "") + "ui-toolbar-back-btn ui-icon-carat-l ui-btn-icon-left' data-" + e.mobile.ns + "rel='back'>" + t.backBtnText + "</a>").prependTo(this.element)
            },
            _addHeadingClasses: function () {
                this.element.children("h1, h2, h3, h4, h5, h6").addClass("ui-title").attr({
                    role: "heading",
                    "aria-level": "1"
                })
            }
        })
    }(e),
    function (e, t) {
        e.widget("mobile.toolbar", e.mobile.toolbar, {
            options: {
                position: null,
                visibleOnPageShow: !0,
                disablePageZoom: !0,
                transition: "slide",
                fullscreen: !1,
                tapToggle: !0,
                tapToggleBlacklist: "a, button, input, select, textarea, .ui-header-fixed, .ui-footer-fixed, .ui-flipswitch, .ui-popup, .ui-panel, .ui-panel-dismiss-open",
                hideDuringFocus: "input, textarea, select",
                updatePagePadding: !0,
                trackPersistentToolbars: !0,
                supportBlacklist: function () {
                    return !e.support.fixedPosition
                }
            },
            _create: function () {
                this._super(), "fixed" === this.options.position && !this.options.supportBlacklist() && this._makeFixed()
            },
            _makeFixed: function () {
                this.element.addClass("ui-" + this.role + "-fixed"), this.updatePagePadding(), this._addTransitionClass(), this._bindPageEvents(), this._bindToggleHandlers()
            },
            _setOptions: function (n) {
                if ("fixed" === n.position && "fixed" !== this.options.position && this._makeFixed(), "fixed" === this.options.position && !this.options.supportBlacklist()) {
                    var r = this.page ? this.page : e(".ui-page-active").length > 0 ? e(".ui-page-active") : e(".ui-page").eq(0);
                    n.fullscreen !== t && (n.fullscreen ? (this.element.addClass("ui-" + this.role + "-fullscreen"), r.addClass("ui-page-" + this.role + "-fullscreen")) : (this.element.removeClass("ui-" + this.role + "-fullscreen"), r.removeClass("ui-page-" + this.role + "-fullscreen").addClass("ui-page-" + this.role + "-fixed")))
                }
                this._super(n)
            },
            _addTransitionClass: function () {
                var e = this.options.transition;
                e && "none" !== e && ("slide" === e && (e = this.element.hasClass("ui-header") ? "slidedown" : "slideup"), this.element.addClass(e))
            },
            _bindPageEvents: function () {
                var e = this.page ? this.element.closest(".ui-page") : this.document;
                this._on(e, {
                    pagebeforeshow: "_handlePageBeforeShow",
                    webkitAnimationStart: "_handleAnimationStart",
                    animationstart: "_handleAnimationStart",
                    updatelayout: "_handleAnimationStart",
                    pageshow: "_handlePageShow",
                    pagebeforehide: "_handlePageBeforeHide"
                })
            },
            _handlePageBeforeShow: function () {
                var t = this.options;
                t.disablePageZoom && e.mobile.zoom.disable(!0), t.visibleOnPageShow || this.hide(!0)
            },
            _handleAnimationStart: function () {
                this.options.updatePagePadding && this.updatePagePadding(this.page ? this.page : ".ui-page-active")
            },
            _handlePageShow: function () {
                this.updatePagePadding(this.page ? this.page : ".ui-page-active"), this.options.updatePagePadding && this._on(this.window, {
                    throttledresize: "updatePagePadding"
                })
            },
            _handlePageBeforeHide: function (t, n) {
                var i, s, o, u, r = this.options;
                r.disablePageZoom && e.mobile.zoom.enable(!0), r.updatePagePadding && this._off(this.window, "throttledresize"), r.trackPersistentToolbars && (i = e(".ui-footer-fixed:jqmData(id)", this.page), s = e(".ui-header-fixed:jqmData(id)", this.page), o = i.length && n.nextPage && e(".ui-footer-fixed:jqmData(id='" + i.jqmData("id") + "')", n.nextPage) || e(), u = s.length && n.nextPage && e(".ui-header-fixed:jqmData(id='" + s.jqmData("id") + "')", n.nextPage) || e(), (o.length || u.length) && (o.add(u).appendTo(e.mobile.pageContainer), n.nextPage.one("pageshow", function () {
                    u.prependTo(this), o.appendTo(this)
                })))
            },
            _visible: !0,
            updatePagePadding: function (n) {
                var r = this.element,
                    i = "header" === this.role,
                    s = parseFloat(r.css(i ? "top" : "bottom"));
                this.options.fullscreen || (n = n && n.type === t && n || this.page || r.closest(".ui-page"), n = this.page ? this.page : ".ui-page-active", e(n).css("padding-" + (i ? "top" : "bottom"), r.outerHeight() + s))
            },
            _useTransition: function (t) {
                var n = this.window,
                    r = this.element,
                    i = n.scrollTop(),
                    s = r.height(),
                    o = this.page ? r.closest(".ui-page").height() : e(".ui-page-active").height(),
                    u = e.mobile.getScreenHeight();
                return !t && (this.options.transition && "none" !== this.options.transition && ("header" === this.role && !this.options.fullscreen && i > s || "footer" === this.role && !this.options.fullscreen && o - s > i + u) || this.options.fullscreen)
            },
            show: function (e) {
                var t = "ui-fixed-hidden",
                    n = this.element;
                this._useTransition(e) ? n.removeClass("out " + t).addClass("in").animationComplete(function () {
                    n.removeClass("in")
                }) : n.removeClass(t), this._visible = !0
            },
            hide: function (e) {
                var t = "ui-fixed-hidden",
                    n = this.element,
                    r = "out" + ("slide" === this.options.transition ? " reverse" : "");
                this._useTransition(e) ? n.addClass(r).removeClass("in").animationComplete(function () {
                    n.addClass(t).removeClass(r)
                }) : n.addClass(t).removeClass(r), this._visible = !1
            },
            toggle: function () {
                this[this._visible ? "hide" : "show"]()
            },
            _bindToggleHandlers: function () {
                var r, i, t = this,
                    n = t.options,
                    s = !0,
                    o = this.page ? this.page : e(".ui-page");
                o.bind("vclick", function (r) {
                    n.tapToggle && !e(r.target).closest(n.tapToggleBlacklist).length && t.toggle()
                }).bind("focusin focusout", function (o) {
                    screen.width < 1025 && e(o.target).is(n.hideDuringFocus) && !e(o.target).closest(".ui-header-fixed, .ui-footer-fixed").length && ("focusout" !== o.type || s ? "focusin" === o.type && !!s && (clearTimeout(r), s = !1, i = setTimeout(function () {
                        t.hide()
                    }, 0)) : (s = !0, clearTimeout(i), r = setTimeout(function () {
                        t.show()
                    }, 0)))
                })
            },
            _setRelative: function () {
                "fixed" !== this.options.position && e("[data-" + e.mobile.ns + "role='page']").css({
                    position: "relative"
                })
            },
            _destroy: function () {
                var e = this.element,
                    t = e.hasClass("ui-header");
                e.closest(".ui-page").css("padding-" + (t ? "top" : "bottom"), ""), e.removeClass("ui-header-fixed ui-footer-fixed ui-header-fullscreen ui-footer-fullscreen in out fade slidedown slideup ui-fixed-hidden"), e.closest(".ui-page").removeClass("ui-page-header-fixed ui-page-footer-fixed ui-page-header-fullscreen ui-page-footer-fullscreen")
            }
        })
    }(e),
    function (e) {
        e.widget("mobile.toolbar", e.mobile.toolbar, {
            _makeFixed: function () {
                this._super(), this._workarounds()
            },
            _workarounds: function () {
                var e = navigator.userAgent,
                    t = navigator.platform,
                    n = e.match(/AppleWebKit\/([0-9]+)/),
                    r = !!n && n[1],
                    i = null,
                    s = this;
                if (t.indexOf("iPhone") > -1 || t.indexOf("iPad") > -1 || t.indexOf("iPod") > -1) i = "ios";
                else {
                    if (!(e.indexOf("Android") > -1)) return;
                    i = "android"
                } if ("ios" === i) s._bindScrollWorkaround();
                else {
                    if (!("android" === i && r && 534 > r)) return;
                    s._bindScrollWorkaround(), s._bindListThumbWorkaround()
                }
            },
            _viewportOffset: function () {
                var e = this.element,
                    t = e.hasClass("ui-header"),
                    n = Math.abs(e.offset().top - this.window.scrollTop());
                return t || (n = Math.round(n - this.window.height() + e.outerHeight()) - 60), n
            },
            _bindScrollWorkaround: function () {
                var e = this;
                this._on(this.window, {
                    scrollstop: function () {
                        var t = e._viewportOffset();
                        t > 2 && e._visible && e._triggerRedraw()
                    }
                })
            },
            _bindListThumbWorkaround: function () {
                this.element.closest(".ui-page").addClass("ui-android-2x-fixed")
            },
            _triggerRedraw: function () {
                var t = parseFloat(e(".ui-page-active").css("padding-bottom"));
                e(".ui-page-active").css("padding-bottom", t + 1 + "px"), setTimeout(function () {
                    e(".ui-page-active").css("padding-bottom", t + "px")
                }, 0)
            },
            destroy: function () {
                this._super(), this.element.closest(".ui-page-active").removeClass("ui-android-2x-fix")
            }
        })
    }(e),
    function (e) {
        e.mobile.behaviors.formReset = {
            _handleFormReset: function () {
                this._on(this.element.closest("form"), {
                    reset: function () {
                        this._delay("_reset")
                    }
                })
            }
        }
    }(e),
    function (e, t) {
        var n = e.mobile.path.hashToSelector;
        e.widget("mobile.checkboxradio", e.extend({
            initSelector: "input:not( :jqmData(role='flipswitch' ) )[type='checkbox'],input[type='radio']:not( :jqmData(role='flipswitch' ))",
            options: {
                theme: "inherit",
                mini: !1,
                wrapperClass: null,
                enhanced: !1,
                iconpos: "left"
            },
            _create: function () {
                var t = this.element,
                    r = this.options,
                    i = function (e, t) {
                        return e.jqmData(t) || e.closest("form, fieldset").jqmData(t)
                    },
                    s = t.closest("label"),
                    o = s.length ? s : t.closest("form, fieldset, :jqmData(role='page'), :jqmData(role='dialog')").find("label").filter("[for='" + n(t[0].id) + "']").first(),
                    u = t[0].type,
                    a = "ui-" + u + "-on",
                    f = "ui-" + u + "-off";
                ("checkbox" === u || "radio" === u) && (this.element[0].disabled && (this.options.disabled = !0), r.iconpos = i(t, "iconpos") || o.attr("data-" + e.mobile.ns + "iconpos") || r.iconpos, r.mini = i(t, "mini") || r.mini, e.extend(this, {
                    input: t,
                    label: o,
                    parentLabel: s,
                    inputtype: u,
                    checkedClass: a,
                    uncheckedClass: f
                }), this.options.enhanced || this._enhance(), this._on(o, {
                    vmouseover: "_handleLabelVMouseOver",
                    vclick: "_handleLabelVClick"
                }), this._on(t, {
                    vmousedown: "_cacheVals",
                    vclick: "_handleInputVClick",
                    focus: "_handleInputFocus",
                    blur: "_handleInputBlur"
                }), this._handleFormReset(), this.refresh())
            },
            _enhance: function () {
                this.label.addClass("ui-btn ui-corner-all"), this.parentLabel.length > 0 ? this.input.add(this.label).wrapAll(this._wrapper()) : (this.element.wrap(this._wrapper()), this.element.parent().prepend(this.label)), this._setOptions({
                    theme: this.options.theme,
                    iconpos: this.options.iconpos,
                    mini: this.options.mini
                })
            },
            _wrapper: function () {
                return e("<div class='" + (this.options.wrapperClass ? this.options.wrapperClass : "") + " ui-" + this.inputtype + (this.options.disabled ? " ui-state-disabled" : "") + "' ></div>")
            },
            _handleInputFocus: function () {
                this.label.addClass(e.mobile.focusClass)
            },
            _handleInputBlur: function () {
                this.label.removeClass(e.mobile.focusClass)
            },
            _handleInputVClick: function () {
                this.element.prop("checked", this.element.is(":checked")), this._getInputSet().not(this.element).prop("checked", !1), this._updateAll()
            },
            _handleLabelVMouseOver: function (e) {
                this.label.parent().hasClass("ui-state-disabled") && e.stopPropagation()
            },
            _handleLabelVClick: function (e) {
                var t = this.element;
                return t.is(":disabled") ? (e.preventDefault(), void 0) : (this._cacheVals(), t.prop("checked", "radio" === this.inputtype && !0 || !t.prop("checked")), t.triggerHandler("click"), this._getInputSet().not(t).prop("checked", !1), this._updateAll(), !1)
            },
            _cacheVals: function () {
                this._getInputSet().each(function () {
                    e(this).attr("data-" + e.mobile.ns + "cacheVal", this.checked)
                })
            },
            _getInputSet: function () {
                var t, r, i = this.element[0],
                    s = i.name,
                    o = i.form,
                    u = this.element.parents().last().get(0),
                    a = this.element;
                return s && "radio" === this.inputtype && u && (t = "input[type='radio'][name='" + n(s) + "']", o ? (r = o.id, r && (a = e(t + "[form='" + n(r) + "']", u)), a = e(o).find(t).filter(function () {
                    return this.form === o
                }).add(a)) : a = e(t, u).filter(function () {
                    return !this.form
                })), a
            },
            _updateAll: function () {
                var t = this;
                this._getInputSet().each(function () {
                    var n = e(this);
                    (this.checked || "checkbox" === t.inputtype) && n.trigger("change")
                }).checkboxradio("refresh")
            },
            _reset: function () {
                this.refresh()
            },
            _hasIcon: function () {
                var t, n, r = e.mobile.controlgroup;
                return r && (t = this.element.closest(":mobile-controlgroup," + r.prototype.initSelector), t.length > 0) ? (n = e.data(t[0], "mobile-controlgroup"), "horizontal" !== (n ? n.options.type : t.attr("data-" + e.mobile.ns + "type"))) : !0
            },
            refresh: function () {
                var t = this._hasIcon(),
                    n = this.element[0].checked,
                    r = e.mobile.activeBtnClass,
                    i = "ui-btn-icon-" + this.options.iconpos,
                    s = [],
                    o = [];
                t ? (o.push(r), s.push(i)) : (o.push(i), (n ? s : o).push(r)), n ? (s.push(this.checkedClass), o.push(this.uncheckedClass)) : (s.push(this.uncheckedClass), o.push(this.checkedClass)), this.label.addClass(s.join(" ")).removeClass(o.join(" "))
            },
            widget: function () {
                return this.label.parent()
            },
            _setOptions: function (e) {
                var n = this.label,
                    r = this.options,
                    i = this.widget(),
                    s = this._hasIcon();
                e.disabled !== t && (this.input.prop("disabled", !!e.disabled), i.toggleClass("ui-state-disabled", !!e.disabled)), e.mini !== t && i.toggleClass("ui-mini", !!e.mini), e.theme !== t && n.removeClass("ui-btn-" + r.theme).addClass("ui-btn-" + e.theme), e.wrapperClass !== t && i.removeClass(r.wrapperClass).addClass(e.wrapperClass), e.iconpos !== t && s ? n.removeClass("ui-btn-icon-" + r.iconpos).addClass("ui-btn-icon-" + e.iconpos) : s || n.removeClass("ui-btn-icon-" + r.iconpos), this._super(e)
            }
        }, e.mobile.behaviors.formReset))
    }(e),
    function (e) {
        var n = e.mobile.getAttribute;
        e.widget("mobile.listview", e.extend({
            options: {
                theme: null,
                countTheme: null,
                dividerTheme: null,
                icon: "carat-r",
                splitIcon: "carat-r",
                splitTheme: null,
                corners: !0,
                shadow: !0,
                inset: !1
            },
            _create: function () {
                var e = this,
                    t = "";
                t += e.options.inset ? " ui-listview-inset" : "", !e.options.inset || (t += e.options.corners ? " ui-corner-all" : "", t += e.options.shadow ? " ui-shadow" : ""), e.element.addClass(" ui-listview" + t), e.refresh(!0)
            },
            _findFirstElementByTagName: function (e, t, n, r) {
                var i = {};
                for (i[n] = i[r] = !0; e;) {
                    if (i[e.nodeName]) return e;
                    e = e[t]
                }
                return null
            },
            _addThumbClasses: function (t) {
                var n, r, i = t.length;
                for (n = 0; i > n; n++) r = e(this._findFirstElementByTagName(t[n].firstChild, "nextSibling", "img", "IMG")), r.length && e(this._findFirstElementByTagName(r[0].parentNode, "parentNode", "li", "LI")).addClass(r.hasClass("ui-li-icon") ? "ui-li-has-icon" : "ui-li-has-thumb")
            },
            _getChildrenByTagName: function (t, n, r) {
                var i = [],
                    s = {};
                for (s[n] = s[r] = !0, t = t.firstChild; t;) s[t.nodeName] && i.push(t), t = t.nextSibling;
                return e(i)
            },
            _beforeListviewRefresh: e.noop,
            _afterListviewRefresh: e.noop,
            refresh: function (t) {
                var r, i, s, o, u, a, f, l, c, h, p, d, v, m, g, y, b, w, E, S, x = this.options,
                    T = this.element,
                    N = !!e.nodeName(T[0], "ol"),
                    C = T.attr("start"),
                    k = {},
                    L = T.find(".ui-li-count"),
                    A = n(T[0], "counttheme") || this.options.countTheme,
                    O = A ? "ui-body-" + A : "ui-body-inherit";
                for (x.theme && T.addClass("ui-group-theme-" + x.theme), N && (C || 0 === C) && (p = parseInt(C, 10) - 1, T.css("counter-reset", "listnumbering " + p)), this._beforeListviewRefresh(), S = this._getChildrenByTagName(T[0], "li", "LI"), i = 0, s = S.length; s > i; i++) o = S.eq(i), u = "", (t || o[0].className.search(/\bui-li-static\b|\bui-li-divider\b/) < 0) && (c = this._getChildrenByTagName(o[0], "a", "A"), h = "list-divider" === n(o[0], "role"), v = o.attr("value"), a = n(o[0], "theme"), c.length && c[0].className.search(/\bui-btn\b/) < 0 && !h ? (f = n(o[0], "icon"), l = f === !1 ? !1 : f || x.icon, c.removeClass("ui-link"), r = "ui-btn", a && (r += " ui-btn-" + a), c.length > 1 ? (u = "ui-li-has-alt", m = c.last(), g = n(m[0], "theme") || x.splitTheme || n(o[0], "theme", !0), y = g ? " ui-btn-" + g : "", b = n(m[0], "icon") || n(o[0], "icon") || x.splitIcon, w = "ui-btn ui-btn-icon-notext ui-icon-" + b + y, m.attr("title", e.trim(m.getEncodedText())).addClass(w).empty()) : l && (r += " ui-btn-icon-right ui-icon-" + l), c.first().addClass(r)) : h ? (E = n(o[0], "theme") || x.dividerTheme || x.theme, u = "ui-li-divider ui-bar-" + (E ? E : "inherit"), o.attr("role", "heading")) : c.length <= 0 && (u = "ui-li-static ui-body-" + (a ? a : "inherit")), N && v && (d = parseInt(v, 10) - 1, o.css("counter-reset", "listnumbering " + d))), k[u] || (k[u] = []), k[u].push(o[0]);
                for (u in k) e(k[u]).addClass(u);
                L.each(function () {
                    e(this).closest("li").addClass("ui-li-has-count")
                }), O && L.addClass(O), this._addThumbClasses(S), this._addThumbClasses(S.find(".ui-btn")), this._afterListviewRefresh(), this._addFirstLastClasses(S, this._getVisibles(S, t), t)
            }
        }, e.mobile.behaviors.addFirstLastClasses))
    }(e),
    function (e) {
        function r(t) {
            var n = e.trim(t.text()) || null;
            return n ? n = n.slice(0, 1).toUpperCase() : null
        }
        e.widget("mobile.listview", e.mobile.listview, {
            options: {
                autodividers: !1,
                autodividersSelector: r
            },
            _beforeListviewRefresh: function () {
                this.options.autodividers && (this._replaceDividers(), this._superApply(arguments))
            },
            _replaceDividers: function () {
                var t, r, i, s, a, o = null,
                    u = this.element;
                for (u.children("li:jqmData(role='list-divider')").remove(), r = u.children("li"), t = 0; t < r.length; t++) i = r[t], s = this.options.autodividersSelector(e(i)), s && o !== s && (a = n.createElement("li"), a.appendChild(n.createTextNode(s)), a.setAttribute("data-" + e.mobile.ns + "role", "list-divider"), i.parentNode.insertBefore(a, i)), o = s
            }
        })
    }(e),
    function (e) {
        var n = /(^|\s)ui-li-divider($|\s)/,
            r = /(^|\s)ui-screen-hidden($|\s)/;
        e.widget("mobile.listview", e.mobile.listview, {
            options: {
                hideDividers: !1
            },
            _afterListviewRefresh: function () {
                var e, t, i, s = !0;
                if (this._superApply(arguments), this.options.hideDividers)
                    for (e = this._getChildrenByTagName(this.element[0], "li", "LI"), t = e.length - 1; t > -1; t--) i = e[t], i.className.match(n) ? (s && (i.className = i.className + " ui-screen-hidden"), s = !0) : i.className.match(r) || (s = !1)
            }
        })
    }(e),
    function (e) {
        var t = "ui-loader",
            n = e("html");
        e.widget("mobile.loader", {
            options: {
                theme: "a",
                textVisible: !1,
                html: "",
                text: "loading"
            },
            defaultHtml: "<div class='" + t + "'><span class='ui-icon-loading'></span><h1></h1></div>",
            fakeFixLoader: function () {
                var t = e("." + e.mobile.activeBtnClass).first();
                this.element.css({
                    top: e.support.scrollTop && this.window.scrollTop() + this.window.height() / 2 || t.length && t.offset().top || 100
                })
            },
            checkLoaderPosition: function () {
                var t = this.element.offset(),
                    n = this.window.scrollTop(),
                    r = e.mobile.getScreenHeight();
                (t.top < n || t.top - n > r) && (this.element.addClass("ui-loader-fakefix"), this.fakeFixLoader(), this.window.unbind("scroll", this.checkLoaderPosition).bind("scroll", e.proxy(this.fakeFixLoader, this)))
            },
            resetHtml: function () {
                this.element.html(e(this.defaultHtml).html())
            },
            show: function (r, i, s) {
                var o, u, a;
                this.resetHtml(), "object" === e.type(r) ? (a = e.extend({}, this.options, r), r = a.theme) : (a = this.options, r = r || a.theme), u = i || (a.text === !1 ? "" : a.text), n.addClass("ui-loading"), o = a.textVisible, this.element.attr("class", t + " ui-corner-all ui-body-" + r + " ui-loader-" + (o || i || r.text ? "verbose" : "default") + (a.textonly || s ? " ui-loader-textonly" : "")), a.html ? this.element.html(a.html) : this.element.find("h1").text(u), this.element.appendTo(e.mobile.pageContainer), this.checkLoaderPosition(), this.window.bind("scroll", e.proxy(this.checkLoaderPosition, this))
            },
            hide: function () {
                n.removeClass("ui-loading"), this.options.text && this.element.removeClass("ui-loader-fakefix"), e.mobile.window.unbind("scroll", this.fakeFixLoader), e.mobile.window.unbind("scroll", this.checkLoaderPosition)
            }
        })
    }(e, this),
    function (e, t) {
        e.widget("mobile.navbar", {
            options: {
                iconpos: "top",
                grid: null
            },
            _create: function () {
                var r = this.element,
                    i = r.find("a"),
                    s = i.filter(":jqmData(icon)").length ? this.options.iconpos : t;
                r.addClass("ui-navbar").attr("role", "navigation").find("ul").jqmEnhanceable().grid({
                    grid: this.options.grid
                }), i.each(function () {
                    var t = e.mobile.getAttribute(this, "icon"),
                        n = e.mobile.getAttribute(this, "theme"),
                        r = "ui-btn";
                    n && (r += " ui-btn-" + n), t && (r += " ui-icon-" + t + " ui-btn-icon-" + s), e(this).addClass(r)
                }), r.delegate("a", "vclick", function () {
                    var t = e(this);
                    t.hasClass("ui-state-disabled") || t.hasClass("ui-disabled") || t.hasClass(e.mobile.activeBtnClass) || (i.removeClass(e.mobile.activeBtnClass), t.addClass(e.mobile.activeBtnClass), e(n).one("pagehide", function () {
                        t.removeClass(e.mobile.activeBtnClass)
                    }))
                }), r.closest(".ui-page").bind("pagebeforeshow", function () {
                    i.filter(".ui-state-persist").addClass(e.mobile.activeBtnClass)
                })
            }
        })
    }(e),
    function (e, t, n) {
        e.widget("mobile.page", e.mobile.page, {
            options: {
                closeBtn: "left",
                closeBtnText: "Close",
                overlayTheme: "a",
                corners: !0,
                dialog: !1
            },
            _create: function () {
                this._super(), this.options.dialog && (e.extend(this, {
                    _inner: this.element.children(),
                    _headerCloseButton: null
                }), this.options.enhanced || this._setCloseBtn(this.options.closeBtn))
            },
            _enhance: function () {
                this._super(), this.options.dialog && this.element.addClass("ui-dialog").wrapInner(e("<div/>", {
                    role: "dialog",
                    "class": "ui-dialog-contain ui-overlay-shadow" + (this.options.corners ? " ui-corner-all" : "")
                }))
            },
            _setOptions: function (t) {
                var r, i, s = this.options;
                t.corners !== n && this._inner.toggleClass("ui-corner-all", !!t.corners), t.overlayTheme !== n && e.mobile.activePage[0] === this.element[0] && (s.overlayTheme = t.overlayTheme, this._handlePageBeforeShow()), t.closeBtnText !== n && (r = s.closeBtn, i = t.closeBtnText), t.closeBtn !== n && (r = t.closeBtn), r && this._setCloseBtn(r, i), this._super(t)
            },
            _handlePageBeforeShow: function () {
                this.options.overlayTheme && this.options.dialog ? (this.removeContainerBackground(), this.setContainerBackground(this.options.overlayTheme)) : this._super()
            },
            _setCloseBtn: function (t, n) {
                var r, i = this._headerCloseButton;
                t = "left" === t ? "left" : "right" === t ? "right" : "none", "none" === t ? i && (i.remove(), i = null) : i ? (i.removeClass("ui-btn-left ui-btn-right").addClass("ui-btn-" + t), n && i.text(n)) : (r = this._inner.find(":jqmData(role='header')").first(), i = e("<a></a>", {
                    href: "#",
                    "class": "ui-btn ui-corner-all ui-icon-delete ui-btn-icon-notext ui-btn-" + t
                }).attr("data-" + e.mobile.ns + "rel", "back").text(n || this.options.closeBtnText || "").prependTo(r)), this._headerCloseButton = i
            }
        })
    }(e, this),
    function (e, n) {
        e.widget("mobile.panel", {
            options: {
                classes: {
                    panel: "ui-panel",
                    panelOpen: "ui-panel-open",
                    panelClosed: "ui-panel-closed",
                    panelFixed: "ui-panel-fixed",
                    panelInner: "ui-panel-inner",
                    modal: "ui-panel-dismiss",
                    modalOpen: "ui-panel-dismiss-open",
                    pageContainer: "ui-panel-page-container",
                    pageWrapper: "ui-panel-wrapper",
                    pageFixedToolbar: "ui-panel-fixed-toolbar",
                    pageContentPrefix: "ui-panel-page-content",
                    animate: "ui-panel-animate"
                },
                animate: !0,
                theme: null,
                position: "left",
                dismissible: !0,
                display: "reveal",
                swipeClose: !0,
                positionFixed: !1
            },
            _closeLink: null,
            _parentPage: null,
            _page: null,
            _modal: null,
            _panelInner: null,
            _wrapper: null,
            _fixedToolbars: null,
            _create: function () {
                var t = this.element,
                    n = t.closest(".ui-page, :jqmData(role='page')");
                e.extend(this, {
                    _closeLink: t.find(":jqmData(rel='close')"),
                    _parentPage: n.length > 0 ? n : !1,
                    _openedPage: null,
                    _page: this._getPage,
                    _panelInner: this._getPanelInner(),
                    _fixedToolbars: this._getFixedToolbars
                }), "overlay" !== this.options.display && this._getWrapper(), this._addPanelClasses(), e.support.cssTransform3d && !!this.options.animate && this.element.addClass(this.options.classes.animate), this._bindUpdateLayout(), this._bindCloseEvents(), this._bindLinkListeners(), this._bindPageEvents(), !this.options.dismissible || this._createModal(), this._bindSwipeEvents()
            },
            _getPanelInner: function () {
                var e = this.element.find("." + this.options.classes.panelInner);
                return 0 === e.length && (e = this.element.children().wrapAll("<div class='" + this.options.classes.panelInner + "' />").parent()), e
            },
            _createModal: function () {
                var t = this,
                    n = t._parentPage ? t._parentPage.parent() : t.element.parent();
                t._modal = e("<div class='" + t.options.classes.modal + "'></div>").on("mousedown", function () {
                    t.close()
                }).appendTo(n)
            },
            _getPage: function () {
                var t = this._openedPage || this._parentPage || e("." + e.mobile.activePageClass);
                return t
            },
            _getWrapper: function () {
                var e = this._page().find("." + this.options.classes.pageWrapper);
                0 === e.length && (e = this._page().children(".ui-header:not(.ui-header-fixed), .ui-content:not(.ui-popup), .ui-footer:not(.ui-footer-fixed)").wrapAll("<div class='" + this.options.classes.pageWrapper + "'></div>").parent()), this._wrapper = e
            },
            _getFixedToolbars: function () {
                var t = e("body").children(".ui-header-fixed, .ui-footer-fixed"),
                    n = this._page().find(".ui-header-fixed, .ui-footer-fixed"),
                    r = t.add(n).addClass(this.options.classes.pageFixedToolbar);
                return r
            },
            _getPosDisplayClasses: function (e) {
                return e + "-position-" + this.options.position + " " + e + "-display-" + this.options.display
            },
            _getPanelClasses: function () {
                var e = this.options.classes.panel + " " + this._getPosDisplayClasses(this.options.classes.panel) + " " + this.options.classes.panelClosed + " ui-body-" + (this.options.theme ? this.options.theme : "inherit");
                return !this.options.positionFixed || (e += " " + this.options.classes.panelFixed), e
            },
            _addPanelClasses: function () {
                this.element.addClass(this._getPanelClasses())
            },
            _handleCloseClickAndEatEvent: function (e) {
                return e.isDefaultPrevented() ? void 0 : (e.preventDefault(), this.close(), !1)
            },
            _handleCloseClick: function (e) {
                e.isDefaultPrevented() || this.close()
            },
            _bindCloseEvents: function () {
                this._on(this._closeLink, {
                    click: "_handleCloseClick"
                }), this._on({
                    "click a:jqmData(ajax='false')": "_handleCloseClick"
                })
            },
            _positionPanel: function (t) {
                var n = this,
                    r = n._panelInner.outerHeight(),
                    i = r > e.mobile.getScreenHeight();
                i || !n.options.positionFixed ? (i && (n._unfixPanel(), e.mobile.resetActivePageHeight(r)), t && this.window[0].scrollTo(0, e.mobile.defaultHomeScroll)) : n._fixPanel()
            },
            _bindFixListener: function () {
                this._on(e(t), {
                    throttledresize: "_positionPanel"
                })
            },
            _unbindFixListener: function () {
                this._off(e(t), "throttledresize")
            },
            _unfixPanel: function () {
                !!this.options.positionFixed && e.support.fixedPosition && this.element.removeClass(this.options.classes.panelFixed)
            },
            _fixPanel: function () {
                !!this.options.positionFixed && e.support.fixedPosition && this.element.addClass(this.options.classes.panelFixed)
            },
            _bindUpdateLayout: function () {
                var e = this;
                e.element.on("updatelayout", function () {
                    e._open && e._positionPanel()
                })
            },
            _bindLinkListeners: function () {
                this._on("body", {
                    "click a": "_handleClick"
                })
            },
            _handleClick: function (t) {
                var r, i = this.element.attr("id");
                return t.currentTarget.href.split("#")[1] === i && i !== n ? (t.preventDefault(), r = e(t.target), r.hasClass("ui-btn") && (r.addClass(e.mobile.activeBtnClass), this.element.one("panelopen panelclose", function () {
                    r.removeClass(e.mobile.activeBtnClass)
                })), this.toggle(), !1) : void 0
            },
            _bindSwipeEvents: function () {
                var e = this,
                    t = e._modal ? e.element.add(e._modal) : e.element;
                !e.options.swipeClose || ("left" === e.options.position ? t.on("swipeleft.panel", function () {
                    e.close()
                }) : t.on("swiperight.panel", function () {
                    e.close()
                }))
            },
            _bindPageEvents: function () {
                var e = this;
                this.document.on("panelbeforeopen", function (t) {
                    e._open && t.target !== e.element[0] && e.close()
                }).on("keyup.panel", function (t) {
                    27 === t.keyCode && e._open && e.close()
                }), !this._parentPage && "overlay" !== this.options.display && this._on(this.document, {
                    pageshow: "_getWrapper"
                }), e._parentPage ? this.document.on("pagehide", ":jqmData(role='page')", function () {
                    e._open && e.close(!0)
                }) : this.document.on("pagebeforehide", function () {
                    e._open && e.close(!0)
                })
            },
            _open: !1,
            _pageContentOpenClasses: null,
            _modalOpenClasses: null,
            open: function (t) {
                if (!this._open) {
                    var n = this,
                        r = n.options,
                        i = function () {
                            n.document.off("panelclose"), n._page().jqmData("panel", "open"), e.support.cssTransform3d && !!r.animate && "overlay" !== r.display && (n._wrapper.addClass(r.classes.animate), n._fixedToolbars().addClass(r.classes.animate)), !t && e.support.cssTransform3d && r.animate ? n.element.animationComplete(s, "transition") : setTimeout(s, 0), r.theme && "overlay" !== r.display && n._page().parent().addClass(r.classes.pageContainer + "-themed " + r.classes.pageContainer + "-" + r.theme), n.element.removeClass(r.classes.panelClosed).addClass(r.classes.panelOpen), n._positionPanel(!0), n._pageContentOpenClasses = n._getPosDisplayClasses(r.classes.pageContentPrefix), "overlay" !== r.display && (n._page().parent().addClass(r.classes.pageContainer), n._wrapper.addClass(n._pageContentOpenClasses), n._fixedToolbars().addClass(n._pageContentOpenClasses)), n._modalOpenClasses = n._getPosDisplayClasses(r.classes.modal) + " " + r.classes.modalOpen, n._modal && n._modal.addClass(n._modalOpenClasses).height(Math.max(n._modal.height(), n.document.height()))
                        },
                        s = function () {
                            "overlay" !== r.display && (n._wrapper.addClass(r.classes.pageContentPrefix + "-open"), n._fixedToolbars().addClass(r.classes.pageContentPrefix + "-open")), n._bindFixListener(), n._trigger("open"), n._openedPage = n._page()
                        };
                    n._trigger("beforeopen"), "open" === n._page().jqmData("panel") ? n.document.on("panelclose", function () {
                        i()
                    }) : i(), n._open = !0
                }
            },
            close: function (t) {
                if (this._open) {
                    var n = this,
                        r = this.options,
                        i = function () {
                            n.element.removeClass(r.classes.panelOpen), "overlay" !== r.display && (n._wrapper.removeClass(n._pageContentOpenClasses), n._fixedToolbars().removeClass(n._pageContentOpenClasses)), !t && e.support.cssTransform3d && r.animate ? n.element.animationComplete(s, "transition") : setTimeout(s, 0), n._modal && n._modal.removeClass(n._modalOpenClasses)
                        },
                        s = function () {
                            r.theme && "overlay" !== r.display && n._page().parent().removeClass(r.classes.pageContainer + "-themed " + r.classes.pageContainer + "-" + r.theme), n.element.addClass(r.classes.panelClosed), "overlay" !== r.display && (n._page().parent().removeClass(r.classes.pageContainer), n._wrapper.removeClass(r.classes.pageContentPrefix + "-open"), n._fixedToolbars().removeClass(r.classes.pageContentPrefix + "-open")), e.support.cssTransform3d && !!r.animate && "overlay" !== r.display && (n._wrapper.removeClass(r.classes.animate), n._fixedToolbars().removeClass(r.classes.animate)), n._fixPanel(), n._unbindFixListener(), e.mobile.resetActivePageHeight(), n._page().jqmRemoveData("panel"), n._trigger("close"), n._openedPage = null
                        };
                    n._trigger("beforeclose"), i(), n._open = !1
                }
            },
            toggle: function () {
                this[this._open ? "close" : "open"]()
            },
            _destroy: function () {
                var t, n = this.options,
                    r = e("body > :mobile-panel").length + e.mobile.activePage.find(":mobile-panel").length > 1;
                "overlay" !== n.display && (t = e("body > :mobile-panel").add(e.mobile.activePage.find(":mobile-panel")), 0 === t.not(".ui-panel-display-overlay").not(this.element).length && this._wrapper.children().unwrap(), this._open && (this._fixedToolbars().removeClass(n.classes.pageContentPrefix + "-open"), e.support.cssTransform3d && !!n.animate && this._fixedToolbars().removeClass(n.classes.animate), this._page().parent().removeClass(n.classes.pageContainer), n.theme && this._page().parent().removeClass(n.classes.pageContainer + "-themed " + n.classes.pageContainer + "-" + n.theme))), r || this.document.off("panelopen panelclose"), this._open && this._page().jqmRemoveData("panel"), this._panelInner.children().unwrap(), this.element.removeClass([this._getPanelClasses(), n.classes.panelOpen, n.classes.animate].join(" ")).off("swipeleft.panel swiperight.panel").off("panelbeforeopen").off("panelhide").off("keyup.panel").off("updatelayout"), this._modal && this._modal.remove()
            }
        })
    }(e),
    function (e, n) {
        function r(e, t, n, r) {
            var i = r;
            return i = t > e ? n + (e - t) / 2 : Math.min(Math.max(n, r - t / 2), n + e - t)
        }

        function i(e) {
            return {
                x: e.scrollLeft(),
                y: e.scrollTop(),
                cx: e[0].innerWidth || e.width(),
                cy: e[0].innerHeight || e.height()
            }
        }
        e.widget("mobile.popup", {
            options: {
                wrapperClass: null,
                theme: null,
                overlayTheme: null,
                shadow: !0,
                corners: !0,
                transition: "none",
                positionTo: "origin",
                tolerance: null,
                closeLinkSelector: "a:jqmData(rel='back')",
                closeLinkEvents: "click.popup",
                navigateEvents: "navigate.popup",
                closeEvents: "navigate.popup pagebeforechange.popup",
                dismissible: !0,
                enhanced: !1,
                history: !e.mobile.browser.oldIE
            },
            _create: function () {
                var t = this.element,
                    n = t.attr("id"),
                    r = this.options;
                r.history = r.history && e.mobile.ajaxEnabled && e.mobile.hashListeningEnabled, e.extend(this, {
                    _scrollTop: 0,
                    _page: t.closest(".ui-page"),
                    _ui: null,
                    _fallbackTransition: "",
                    _currentTransition: !1,
                    _prerequisites: null,
                    _isOpen: !1,
                    _tolerance: null,
                    _resizeData: null,
                    _ignoreResizeTo: 0,
                    _orientationchangeInProgress: !1
                }), 0 === this._page.length && (this._page = e("body")), r.enhanced ? this._ui = {
                    container: t.parent(),
                    screen: t.parent().prev(),
                    placeholder: e(this.document[0].getElementById(n + "-placeholder"))
                } : (this._ui = this._enhance(t, n), this._applyTransition(r.transition)), this._setTolerance(r.tolerance)._ui.focusElement = this._ui.container, this._on(this._ui.screen, {
                    vclick: "_eatEventAndClose"
                }), this._on(this.window, {
                    orientationchange: e.proxy(this, "_handleWindowOrientationchange"),
                    resize: e.proxy(this, "_handleWindowResize"),
                    keyup: e.proxy(this, "_handleWindowKeyUp")
                }), this._on(this.document, {
                    focusin: "_handleDocumentFocusIn"
                })
            },
            _enhance: function (t, n) {
                var r = this.options,
                    i = r.wrapperClass,
                    s = {
                        screen: e("<div class='ui-screen-hidden ui-popup-screen " + this._themeClassFromOption("ui-overlay-", r.overlayTheme) + "'></div>"),
                        placeholder: e("<div style='display: none;'><!-- placeholder --></div>"),
                        container: e("<div class='ui-popup-container ui-popup-hidden ui-popup-truncate" + (i ? " " + i : "") + "'></div>")
                    },
                    o = this.document[0].createDocumentFragment();
                return o.appendChild(s.screen[0]), o.appendChild(s.container[0]), n && (s.screen.attr("id", n + "-screen"), s.container.attr("id", n + "-popup"), s.placeholder.attr("id", n + "-placeholder").html("<!-- placeholder for " + n + " -->")), this._page[0].appendChild(o), s.placeholder.insertAfter(t), t.detach().addClass("ui-popup " + this._themeClassFromOption("ui-body-", r.theme) + " " + (r.shadow ? "ui-overlay-shadow " : "") + (r.corners ? "ui-corner-all " : "")).appendTo(s.container), s
            },
            _eatEventAndClose: function (e) {
                return e.preventDefault(), e.stopImmediatePropagation(), this.options.dismissible && this.close(), !1
            },
            _resizeScreen: function () {
                var e = this._ui.screen,
                    t = this._ui.container.outerHeight(!0),
                    n = e.removeAttr("style").height(),
                    r = this.document.height() - 1;
                r > n ? e.height(r) : t > n && e.height(t)
            },
            _handleWindowKeyUp: function (t) {
                return this._isOpen && t.keyCode === e.mobile.keyCode.ESCAPE ? this._eatEventAndClose(t) : void 0
            },
            _expectResizeEvent: function () {
                var e = i(this.window);
                if (this._resizeData) {
                    if (e.x === this._resizeData.windowCoordinates.x && e.y === this._resizeData.windowCoordinates.y && e.cx === this._resizeData.windowCoordinates.cx && e.cy === this._resizeData.windowCoordinates.cy) return !1;
                    clearTimeout(this._resizeData.timeoutId)
                }
                return this._resizeData = {
                    timeoutId: this._delay("_resizeTimeout", 200),
                    windowCoordinates: e
                }, !0
            },
            _resizeTimeout: function () {
                this._isOpen ? this._expectResizeEvent() || (this._ui.container.hasClass("ui-popup-hidden") && (this._ui.container.removeClass("ui-popup-hidden ui-popup-truncate"), this.reposition({
                    positionTo: "window"
                }), this._ignoreResizeEvents()), this._resizeScreen(), this._resizeData = null, this._orientationchangeInProgress = !1) : (this._resizeData = null, this._orientationchangeInProgress = !1)
            },
            _stopIgnoringResizeEvents: function () {
                this._ignoreResizeTo = 0
            },
            _ignoreResizeEvents: function () {
                this._ignoreResizeTo && clearTimeout(this._ignoreResizeTo), this._ignoreResizeTo = this._delay("_stopIgnoringResizeEvents", 1e3)
            },
            _handleWindowResize: function () {
                this._isOpen && 0 === this._ignoreResizeTo && (this._expectResizeEvent() || this._orientationchangeInProgress) && !this._ui.container.hasClass("ui-popup-hidden") && this._ui.container.addClass("ui-popup-hidden ui-popup-truncate").removeAttr("style")
            },
            _handleWindowOrientationchange: function () {
                !this._orientationchangeInProgress && this._isOpen && 0 === this._ignoreResizeTo && (this._expectResizeEvent(), this._orientationchangeInProgress = !0)
            },
            _handleDocumentFocusIn: function (t) {
                var n, r = t.target,
                    i = this._ui;
                if (this._isOpen) {
                    if (r !== i.container[0]) {
                        if (n = e(r), 0 === n.parents().filter(i.container[0]).length) return e(this.document[0].activeElement).one("focus", function () {
                            n.blur()
                        }), i.focusElement.focus(), t.preventDefault(), t.stopImmediatePropagation(), !1;
                        i.focusElement[0] === i.container[0] && (i.focusElement = n)
                    }
                    this._ignoreResizeEvents()
                }
            },
            _themeClassFromOption: function (e, t) {
                return t ? "none" === t ? "" : e + t : e + "inherit"
            },
            _applyTransition: function (t) {
                return t && (this._ui.container.removeClass(this._fallbackTransition), "none" !== t && (this._fallbackTransition = e.mobile._maybeDegradeTransition(t), "none" === this._fallbackTransition && (this._fallbackTransition = ""), this._ui.container.addClass(this._fallbackTransition))), this
            },
            _setOptions: function (e) {
                var t = this.options,
                    r = this.element,
                    i = this._ui.screen;
                return e.wrapperClass !== n && this._ui.container.removeClass(t.wrapperClass).addClass(e.wrapperClass), e.theme !== n && r.removeClass(this._themeClassFromOption("ui-body-", t.theme)).addClass(this._themeClassFromOption("ui-body-", e.theme)), e.overlayTheme !== n && (i.removeClass(this._themeClassFromOption("ui-overlay-", t.overlayTheme)).addClass(this._themeClassFromOption("ui-overlay-", e.overlayTheme)), this._isOpen && i.addClass("in")), e.shadow !== n && r.toggleClass("ui-overlay-shadow", e.shadow), e.corners !== n && r.toggleClass("ui-corner-all", e.corners), e.transition !== n && (this._currentTransition || this._applyTransition(e.transition)), e.tolerance !== n && this._setTolerance(e.tolerance), e.disabled !== n && e.disabled && this.close(), this._super(e)
            },
            _setTolerance: function (t) {
                var i, r = {
                    t: 30,
                    r: 15,
                    b: 30,
                    l: 15
                };
                if (t !== n) switch (i = String(t).split(","), e.each(i, function (e, t) {
                    i[e] = parseInt(t, 10)
                }), i.length) {
                case 1:
                    isNaN(i[0]) || (r.t = r.r = r.b = r.l = i[0]);
                    break;
                case 2:
                    isNaN(i[0]) || (r.t = r.b = i[0]), isNaN(i[1]) || (r.l = r.r = i[1]);
                    break;
                case 4:
                    isNaN(i[0]) || (r.t = i[0]), isNaN(i[1]) || (r.r = i[1]), isNaN(i[2]) || (r.b = i[2]), isNaN(i[3]) || (r.l = i[3])
                }
                return this._tolerance = r, this
            },
            _clampPopupWidth: function (e) {
                var t, n = i(this.window),
                    r = {
                        x: this._tolerance.l,
                        y: n.y + this._tolerance.t,
                        cx: n.cx - this._tolerance.l - this._tolerance.r,
                        cy: n.cy - this._tolerance.t - this._tolerance.b
                    };
                return e || this._ui.container.css("max-width", r.cx), t = {
                    cx: this._ui.container.outerWidth(!0),
                    cy: this._ui.container.outerHeight(!0)
                }, {
                    rc: r,
                    menuSize: t
                }
            },
            _calculateFinalLocation: function (e, t) {
                var n, i = t.rc,
                    s = t.menuSize;
                return n = {
                    left: r(i.cx, s.cx, i.x, e.x),
                    top: r(i.cy, s.cy, i.y, e.y)
                }, n.top = Math.max(0, n.top), n.top -= Math.min(n.top, Math.max(0, n.top + s.cy - this.document.height())), n
            },
            _placementCoords: function (e) {
                return this._calculateFinalLocation(e, this._clampPopupWidth())
            },
            _createPrerequisites: function (t, n, r) {
                var i, s = this;
                i = {
                    screen: e.Deferred(),
                    container: e.Deferred()
                }, i.screen.then(function () {
                    i === s._prerequisites && t()
                }), i.container.then(function () {
                    i === s._prerequisites && n()
                }), e.when(i.screen, i.container).done(function () {
                    i === s._prerequisites && (s._prerequisites = null, r())
                }), s._prerequisites = i
            },
            _animate: function (t) {
                return this._ui.screen.removeClass(t.classToRemove).addClass(t.screenClassToAdd), t.prerequisites.screen.resolve(), t.transition && "none" !== t.transition && (t.applyTransition && this._applyTransition(t.transition), this._fallbackTransition) ? (this._ui.container.addClass(t.containerClassToAdd).removeClass(t.classToRemove).animationComplete(e.proxy(t.prerequisites.container, "resolve")), void 0) : (this._ui.container.removeClass(t.classToRemove), t.prerequisites.container.resolve(), void 0)
            },
            _desiredCoords: function (t) {
                var n, r = null,
                    s = i(this.window),
                    o = t.x,
                    u = t.y,
                    a = t.positionTo;
                if (a && "origin" !== a)
                    if ("window" === a) o = s.cx / 2 + s.x, u = s.cy / 2 + s.y;
                    else {
                        try {
                            r = e(a)
                        } catch (f) {
                            r = null
                        }
                        r && (r.filter(":visible"), 0 === r.length && (r = null))
                    }
                return r && (n = r.offset(), o = n.left + r.outerWidth() / 2, u = n.top + r.outerHeight() / 2), ("number" !== e.type(o) || isNaN(o)) && (o = s.cx / 2 + s.x), ("number" !== e.type(u) || isNaN(u)) && (u = s.cy / 2 + s.y), {
                    x: o,
                    y: u
                }
            },
            _reposition: function (e) {
                e = {
                    x: e.x,
                    y: e.y,
                    positionTo: e.positionTo
                }, this._trigger("beforeposition", n, e), this._ui.container.offset(this._placementCoords(this._desiredCoords(e)))
            },
            reposition: function (e) {
                this._isOpen && this._reposition(e)
            },
            _openPrerequisitesComplete: function () {
                var e = this.element.attr("id");
                this._ui.container.addClass("ui-popup-active"), this._isOpen = !0, this._resizeScreen(), this._ui.container.attr("tabindex", "0").focus(), this._ignoreResizeEvents(), e && this.document.find("[aria-haspopup='true'][aria-owns='" + e + "']").attr("aria-expanded", !0), this._trigger("afteropen")
            },
            _open: function (t) {
                var n = e.extend({}, this.options, t),
                    r = function () {
                        var e = navigator.userAgent,
                            t = e.match(/AppleWebKit\/([0-9\.]+)/),
                            n = !!t && t[1],
                            r = e.match(/Android (\d+(?:\.\d+))/),
                            i = !!r && r[1],
                            s = e.indexOf("Chrome") > -1;
                        return null !== r && "4.0" === i && n && n > 534.13 && !s ? !0 : !1
                    }();
                this._createPrerequisites(e.noop, e.noop, e.proxy(this, "_openPrerequisitesComplete")), this._currentTransition = n.transition, this._applyTransition(n.transition), this._ui.screen.removeClass("ui-screen-hidden"), this._ui.container.removeClass("ui-popup-truncate"), this._reposition(n), this._ui.container.removeClass("ui-popup-hidden"), this.options.overlayTheme && r && this.element.closest(".ui-page").addClass("ui-popup-open"), this._animate({
                    additionalCondition: !0,
                    transition: n.transition,
                    classToRemove: "",
                    screenClassToAdd: "in",
                    containerClassToAdd: "in",
                    applyTransition: !1,
                    prerequisites: this._prerequisites
                })
            },
            _closePrerequisiteScreen: function () {
                this._ui.screen.removeClass("out").addClass("ui-screen-hidden")
            },
            _closePrerequisiteContainer: function () {
                this._ui.container.removeClass("reverse out").addClass("ui-popup-hidden ui-popup-truncate").removeAttr("style")
            },
            _closePrerequisitesDone: function () {
                var t = this._ui.container,
                    r = this.element.attr("id");
                t.removeAttr("tabindex"), e.mobile.popup.active = n, e(":focus", t[0]).add(t[0]).blur(), r && this.document.find("[aria-haspopup='true'][aria-owns='" + r + "']").attr("aria-expanded", !1), this._trigger("afterclose")
            },
            _close: function (t) {
                this._ui.container.removeClass("ui-popup-active"), this._page.removeClass("ui-popup-open"), this._isOpen = !1, this._createPrerequisites(e.proxy(this, "_closePrerequisiteScreen"), e.proxy(this, "_closePrerequisiteContainer"), e.proxy(this, "_closePrerequisitesDone")), this._animate({
                    additionalCondition: this._ui.screen.hasClass("in"),
                    transition: t ? "none" : this._currentTransition,
                    classToRemove: "in",
                    screenClassToAdd: "out",
                    containerClassToAdd: "reverse out",
                    applyTransition: !0,
                    prerequisites: this._prerequisites
                })
            },
            _unenhance: function () {
                this.options.enhanced || (this._setOptions({
                    theme: e.mobile.popup.prototype.options.theme
                }), this.element.detach().insertAfter(this._ui.placeholder).removeClass("ui-popup ui-overlay-shadow ui-corner-all ui-body-inherit"), this._ui.screen.remove(), this._ui.container.remove(), this._ui.placeholder.remove())
            },
            _destroy: function () {
                return e.mobile.popup.active === this ? (this.element.one("popupafterclose", e.proxy(this, "_unenhance")), this.close()) : this._unenhance(), this
            },
            _closePopup: function (n, r) {
                var i, s, o = this.options,
                    u = !1;
                n && n.isDefaultPrevented() || e.mobile.popup.active !== this || (t.scrollTo(0, this._scrollTop), n && "pagebeforechange" === n.type && r && (i = "string" == typeof r.toPage ? r.toPage : r.toPage.jqmData("url"), i = e.mobile.path.parseUrl(i), s = i.pathname + i.search + i.hash, this._myUrl !== e.mobile.path.makeUrlAbsolute(s) ? u = !0 : n.preventDefault()), this.window.off(o.closeEvents), this.element.undelegate(o.closeLinkSelector, o.closeLinkEvents), this._close(u))
            },
            _bindContainerClose: function () {
                this.window.on(this.options.closeEvents, e.proxy(this, "_closePopup"))
            },
            widget: function () {
                return this._ui.container
            },
            open: function (t) {
                var n, r, i, s, o, u, a = this,
                    f = this.options;
                return e.mobile.popup.active || f.disabled ? this : (e.mobile.popup.active = this, this._scrollTop = this.window.scrollTop(), f.history ? (u = e.mobile.navigate.history, r = e.mobile.dialogHashKey, i = e.mobile.activePage, s = i ? i.hasClass("ui-dialog") : !1, this._myUrl = n = u.getActive().url, o = n.indexOf(r) > -1 && !s && u.activeIndex > 0, o ? (a._open(t), a._bindContainerClose(), this) : (-1 !== n.indexOf(r) || s ? n = e.mobile.path.parseLocation().hash + r : n += n.indexOf("#") > -1 ? r : "#" + r, 0 === u.activeIndex && n === u.initialDst && (n += r), this.window.one("beforenavigate", function (e) {
                    e.preventDefault(), a._open(t), a._bindContainerClose()
                }), this.urlAltered = !0, e.mobile.navigate(n, {
                    role: "dialog"
                }), this)) : (a._open(t), a._bindContainerClose(), a.element.delegate(f.closeLinkSelector, f.closeLinkEvents, function (e) {
                    a.close(), e.preventDefault()
                }), this))
            },
            close: function () {
                return e.mobile.popup.active !== this ? this : (this._scrollTop = this.window.scrollTop(), this.options.history && this.urlAltered ? (e.mobile.back(), this.urlAltered = !1) : this._closePopup(), this)
            }
        }), e.mobile.popup.handleLink = function (t) {
            var n, r = e.mobile.path,
                i = e(r.hashToSelector(r.parseUrl(t.attr("href")).hash)).first();
            i.length > 0 && i.data("mobile-popup") && (n = t.offset(), i.popup("open", {
                x: n.left + t.outerWidth() / 2,
                y: n.top + t.outerHeight() / 2,
                transition: t.jqmData("transition"),
                positionTo: t.jqmData("position-to")
            })), setTimeout(function () {
                t.removeClass(e.mobile.activeBtnClass)
            }, 300)
        }, e.mobile.document.on("pagebeforechange", function (t, n) {
            "popup" === n.options.role && (e.mobile.popup.handleLink(n.options.link), t.preventDefault())
        })
    }(e),
    function (e, t) {
        function i() {
            var e = r.clone(),
                t = e.eq(0),
                n = e.eq(1),
                i = n.children();
            return {
                arEls: n.add(t),
                gd: t,
                ct: n,
                ar: i
            }
        }
        var n = e.mobile.browser.oldIE && e.mobile.browser.oldIE <= 8,
            r = e("<div class='ui-popup-arrow-guide'></div><div class='ui-popup-arrow-container" + (n ? " ie" : "") + "'><div class='ui-popup-arrow'></div></div>");
        e.widget("mobile.popup", e.mobile.popup, {
            options: {
                arrow: ""
            },
            _create: function () {
                var e, t = this._super();
                return this.options.arrow && (this._ui.arrow = e = this._addArrow()), t
            },
            _addArrow: function () {
                var e, t = this.options,
                    n = i();
                return e = this._themeClassFromOption("ui-body-", t.theme), n.ar.addClass(e + (t.shadow ? " ui-overlay-shadow" : "")), n.arEls.hide().appendTo(this.element), n
            },
            _unenhance: function () {
                var e = this._ui.arrow;
                return e && e.arEls.remove(), this._super()
            },
            _tryAnArrow: function (e, t, n, r, i) {
                var s, o, u, a = {},
                    f = {};
                return r.arFull[e.dimKey] > r.guideDims[e.dimKey] ? i : (a[e.fst] = n[e.fst] + (r.arHalf[e.oDimKey] + r.menuHalf[e.oDimKey]) * e.offsetFactor - r.contentBox[e.fst] + (r.clampInfo.menuSize[e.oDimKey] - r.contentBox[e.oDimKey]) * e.arrowOffsetFactor, a[e.snd] = n[e.snd], s = r.result || this._calculateFinalLocation(a, r.clampInfo), o = {
                    x: s.left,
                    y: s.top
                }, f[e.fst] = o[e.fst] + r.contentBox[e.fst] + e.tipOffset, f[e.snd] = Math.max(s[e.prop] + r.guideOffset[e.prop] + r.arHalf[e.dimKey], Math.min(s[e.prop] + r.guideOffset[e.prop] + r.guideDims[e.dimKey] - r.arHalf[e.dimKey], n[e.snd])), u = Math.abs(n.x - f.x) + Math.abs(n.y - f.y), (!i || u < i.diff) && (f[e.snd] -= r.arHalf[e.dimKey] + s[e.prop] + r.contentBox[e.snd], i = {
                    dir: t,
                    diff: u,
                    result: s,
                    posProp: e.prop,
                    posVal: f[e.snd]
                }), i)
            },
            _getPlacementState: function (e) {
                var t, n, r = this._ui.arrow,
                    i = {
                        clampInfo: this._clampPopupWidth(!e),
                        arFull: {
                            cx: r.ct.width(),
                            cy: r.ct.height()
                        },
                        guideDims: {
                            cx: r.gd.width(),
                            cy: r.gd.height()
                        },
                        guideOffset: r.gd.offset()
                    };
                return t = this.element.offset(), r.gd.css({
                    left: 0,
                    top: 0,
                    right: 0,
                    bottom: 0
                }), n = r.gd.offset(), i.contentBox = {
                    x: n.left - t.left,
                    y: n.top - t.top,
                    cx: r.gd.width(),
                    cy: r.gd.height()
                }, r.gd.removeAttr("style"), i.guideOffset = {
                    left: i.guideOffset.left - t.left,
                    top: i.guideOffset.top - t.top
                }, i.arHalf = {
                    cx: i.arFull.cx / 2,
                    cy: i.arFull.cy / 2
                }, i.menuHalf = {
                    cx: i.clampInfo.menuSize.cx / 2,
                    cy: i.clampInfo.menuSize.cy / 2
                }, i
            },
            _placementCoords: function (t) {
                var r, i, s, o, u, a = this.options.arrow,
                    f = this._ui.arrow;
                return f ? (f.arEls.show(), u = {}, r = this._getPlacementState(!0), s = {
                    l: {
                        fst: "x",
                        snd: "y",
                        prop: "top",
                        dimKey: "cy",
                        oDimKey: "cx",
                        offsetFactor: 1,
                        tipOffset: -r.arHalf.cx,
                        arrowOffsetFactor: 0
                    },
                    r: {
                        fst: "x",
                        snd: "y",
                        prop: "top",
                        dimKey: "cy",
                        oDimKey: "cx",
                        offsetFactor: -1,
                        tipOffset: r.arHalf.cx + r.contentBox.cx,
                        arrowOffsetFactor: 1
                    },
                    b: {
                        fst: "y",
                        snd: "x",
                        prop: "left",
                        dimKey: "cx",
                        oDimKey: "cy",
                        offsetFactor: -1,
                        tipOffset: r.arHalf.cy + r.contentBox.cy,
                        arrowOffsetFactor: 1
                    },
                    t: {
                        fst: "y",
                        snd: "x",
                        prop: "left",
                        dimKey: "cx",
                        oDimKey: "cy",
                        offsetFactor: 1,
                        tipOffset: -r.arHalf.cy,
                        arrowOffsetFactor: 0
                    }
                }, e.each((a === !0 ? "l,t,r,b" : a).split(","), e.proxy(function (e, n) {
                    i = this._tryAnArrow(s[n], n, t, r, i)
                }, this)), i ? (f.ct.removeClass("ui-popup-arrow-l ui-popup-arrow-t ui-popup-arrow-r ui-popup-arrow-b").addClass("ui-popup-arrow-" + i.dir).removeAttr("style").css(i.posProp, i.posVal).show(), n || (o = this.element.offset(), u[s[i.dir].fst] = f.ct.offset(), u[s[i.dir].snd] = {
                    left: o.left + r.contentBox.x,
                    top: o.top + r.contentBox.y
                }), i.result) : (f.arEls.hide(), this._super(t))) : this._super(t)
            },
            _setOptions: function (e) {
                var n, r = this.options.theme,
                    i = this._ui.arrow,
                    s = this._super(e);
                if (e.arrow !== t) {
                    if (!i && e.arrow) return this._ui.arrow = this._addArrow(), void 0;
                    i && !e.arrow && (i.arEls.remove(), this._ui.arrow = null)
                }
                return i = this._ui.arrow, i && (e.theme !== t && (r = this._themeClassFromOption("ui-body-", r), n = this._themeClassFromOption("ui-body-", e.theme), i.ar.removeClass(r).addClass(n)), e.shadow !== t && i.ar.toggleClass("ui-overlay-shadow", e.shadow)), s
            },
            _destroy: function () {
                var e = this._ui.arrow;
                return e && e.arEls.remove(), this._super()
            }
        })
    }(e),
    function (e, t) {
        e.widget("mobile.table", {
            options: {
                classes: {
                    table: "ui-table"
                },
                enhanced: !1
            },
            _create: function () {
                this.options.enhanced || this.element.addClass(this.options.classes.table), e.extend(this, {
                    headers: t,
                    allHeaders: t
                }), this._refresh(!0)
            },
            _setHeaders: function () {
                var e = this.element.find("thead tr");
                this.headers = this.element.find("tr:eq(0)").children(), this.allHeaders = this.headers.add(e.children())
            },
            refresh: function () {
                this._refresh()
            },
            rebuild: e.noop,
            _refresh: function () {
                var t = this.element,
                    n = t.find("thead tr");
                this._setHeaders(), n.each(function () {
                    var r = 0;
                    e(this).children().each(function () {
                        var o, i = parseInt(this.getAttribute("colspan"), 10),
                            s = ":nth-child(" + (r + 1) + ")";
                        if (this.setAttribute("data-" + e.mobile.ns + "colstart", r + 1), i)
                            for (o = 0; i - 1 > o; o++) r++, s += ", :nth-child(" + (r + 1) + ")";
                        e(this).jqmData("cells", t.find("tr").not(n.eq(0)).not(this).children(s)), r++
                    })
                })
            }
        })
    }(e),
    function (e) {
        e.widget("mobile.table", e.mobile.table, {
            options: {
                mode: "columntoggle",
                columnBtnTheme: null,
                columnPopupTheme: null,
                columnBtnText: "Columns...",
                classes: e.extend(e.mobile.table.prototype.options.classes, {
                    popup: "ui-table-columntoggle-popup",
                    columnBtn: "ui-table-columntoggle-btn",
                    priorityPrefix: "ui-table-priority-",
                    columnToggleTable: "ui-table-columntoggle"
                })
            },
            _create: function () {
                this._super(), "columntoggle" === this.options.mode && (e.extend(this, {
                    _menu: null
                }), this.options.enhanced ? (this._menu = e(this.document[0].getElementById(this._id() + "-popup")).children().first(), this._addToggles(this._menu, !0)) : (this._menu = this._enhanceColToggle(), this.element.addClass(this.options.classes.columnToggleTable)), this._setupEvents(), this._setToggleState())
            },
            _id: function () {
                return this.element.attr("id") || this.widgetName + this.uuid
            },
            _setupEvents: function () {
                this._on(this.window, {
                    throttledresize: "_setToggleState"
                }), this._on(this._menu, {
                    "change input": "_menuInputChange"
                })
            },
            _addToggles: function (t, n) {
                var r, i = 0,
                    s = this.options,
                    o = t.controlgroup("container");
                n ? r = t.find("input") : o.empty(), this.headers.not("td").each(function () {
                    var t = e(this),
                        u = e.mobile.getAttribute(this, "priority"),
                        a = t.add(t.jqmData("cells"));
                    u && (a.addClass(s.classes.priorityPrefix + u), (n ? r.eq(i++) : e("<label><input type='checkbox' checked />" + (t.children("abbr").first().attr("title") || t.text()) + "</label>").appendTo(o).children(0).checkboxradio({
                        theme: s.columnPopupTheme
                    })).jqmData("cells", a))
                }), n || t.controlgroup("refresh")
            },
            _menuInputChange: function (t) {
                var n = e(t.target),
                    r = n[0].checked;
                n.jqmData("cells").toggleClass("ui-table-cell-hidden", !r).toggleClass("ui-table-cell-visible", r), n[0].getAttribute("locked") ? (n.removeAttr("locked"), this._unlockCells(n.jqmData("cells"))) : n.attr("locked", !0)
            },
            _unlockCells: function (e) {
                e.removeClass("ui-table-cell-hidden ui-table-cell-visible")
            },
            _enhanceColToggle: function () {
                var t, n, r, i, s = this.element,
                    o = this.options,
                    u = e.mobile.ns,
                    a = this.document[0].createDocumentFragment();
                return t = this._id() + "-popup", n = e("<a href='#" + t + "' class='" + o.classes.columnBtn + " ui-btn ui-btn-" + (o.columnBtnTheme || "a") + " ui-corner-all ui-shadow ui-mini' data-" + u + "rel='popup'>" + o.columnBtnText + "</a>"), r = e("<div class='" + o.classes.popup + "' id='" + t + "'></div>"), i = e("<fieldset></fieldset>").controlgroup(), this._addToggles(i, !1), i.appendTo(r), a.appendChild(r[0]), a.appendChild(n[0]), s.before(a), r.popup(), i
            },
            rebuild: function () {
                this._super(), "columntoggle" === this.options.mode && this._refresh(!1)
            },
            _refresh: function (e) {
                this._super(e), !e && "columntoggle" === this.options.mode && (this._unlockCells(this.element.find(".ui-table-cell-hidden, .ui-table-cell-visible")), this._addToggles(this._menu, e), this._setToggleState())
            },
            _setToggleState: function () {
                this._menu.find("input").each(function () {
                    var t = e(this);
                    this.checked = "table-cell" === t.jqmData("cells").eq(0).css("display"), t.checkboxradio("refresh")
                })
            },
            _destroy: function () {
                this._super()
            }
        })
    }(e),
    function (e) {
        e.widget("mobile.table", e.mobile.table, {
            options: {
                mode: "reflow",
                classes: e.extend(e.mobile.table.prototype.options.classes, {
                    reflowTable: "ui-table-reflow",
                    cellLabels: "ui-table-cell-label"
                })
            },
            _create: function () {
                this._super(), "reflow" === this.options.mode && (this.options.enhanced || (this.element.addClass(this.options.classes.reflowTable), this._updateReflow()))
            },
            rebuild: function () {
                this._super(), "reflow" === this.options.mode && this._refresh(!1)
            },
            _refresh: function (e) {
                this._super(e), !e && "reflow" === this.options.mode && this._updateReflow()
            },
            _updateReflow: function () {
                var t = this,
                    n = this.options;
                e(t.allHeaders.get().reverse()).each(function () {
                    var u, a, r = e(this).jqmData("cells"),
                        i = e.mobile.getAttribute(this, "colstart"),
                        s = r.not(this).filter("thead th").length && " ui-table-cell-label-top",
                        o = e(this).text();
                    "" !== o && (s ? (u = parseInt(this.getAttribute("colspan"), 10), a = "", u && (a = "td:nth-child(" + u + "n + " + i + ")"), t._addLabels(r.filter(a), n.classes.cellLabels + s, o)) : t._addLabels(r, n.classes.cellLabels, o))
                })
            },
            _addLabels: function (e, t, n) {
                e.not(":has(b." + t + ")").prepend("<b class='" + t + "'>" + n + "</b>")
            }
        })
    }(e),
    function (e, t) {
        function i() {
            return ++n
        }

        function s(e) {
            return e.hash.length > 1 && decodeURIComponent(e.href.replace(r, "")) === decodeURIComponent(location.href.replace(r, ""))
        }
        var n = 0,
            r = /#.*$/;
        e.widget("ui.tabs", {
            version: "fadf2b312a05040436451c64bbfaf4814bc62c56",
            delay: 300,
            options: {
                active: null,
                collapsible: !1,
                event: "click",
                heightStyle: "content",
                hide: null,
                show: null,
                activate: null,
                beforeActivate: null,
                beforeLoad: null,
                load: null
            },
            _create: function () {
                var t = this,
                    n = this.options;
                this.running = !1, this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible", n.collapsible).delegate(".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function (t) {
                    e(this).is(".ui-state-disabled") && t.preventDefault()
                }).delegate(".ui-tabs-anchor", "focus" + this.eventNamespace, function () {
                    e(this).closest("li").is(".ui-state-disabled") && this.blur()
                }), this._processTabs(), n.active = this._initialActive(), e.isArray(n.disabled) && (n.disabled = e.unique(n.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"), function (e) {
                    return t.tabs.index(e)
                }))).sort()), this.active = this.options.active !== !1 && this.anchors.length ? this._findActive(n.active) : e(), this._refresh(), this.active.length && this.load(n.active)
            },
            _initialActive: function () {
                var t = this.options.active,
                    n = this.options.collapsible,
                    r = location.hash.substring(1);
                return null === t && (r && this.tabs.each(function (n, i) {
                    return e(i).attr("aria-controls") === r ? (t = n, !1) : void 0
                }), null === t && (t = this.tabs.index(this.tabs.filter(".ui-tabs-active"))), (null === t || -1 === t) && (t = this.tabs.length ? 0 : !1)), t !== !1 && (t = this.tabs.index(this.tabs.eq(t)), -1 === t && (t = n ? !1 : 0)), !n && t === !1 && this.anchors.length && (t = 0), t
            },
            _getCreateEventData: function () {
                return {
                    tab: this.active,
                    panel: this.active.length ? this._getPanelForTab(this.active) : e()
                }
            },
            _tabKeydown: function (t) {
                var n = e(this.document[0].activeElement).closest("li"),
                    r = this.tabs.index(n),
                    i = !0;
                if (!this._handlePageNav(t)) {
                    switch (t.keyCode) {
                    case e.ui.keyCode.RIGHT:
                    case e.ui.keyCode.DOWN:
                        r++;
                        break;
                    case e.ui.keyCode.UP:
                    case e.ui.keyCode.LEFT:
                        i = !1, r--;
                        break;
                    case e.ui.keyCode.END:
                        r = this.anchors.length - 1;
                        break;
                    case e.ui.keyCode.HOME:
                        r = 0;
                        break;
                    case e.ui.keyCode.SPACE:
                        return t.preventDefault(), clearTimeout(this.activating), this._activate(r), void 0;
                    case e.ui.keyCode.ENTER:
                        return t.preventDefault(), clearTimeout(this.activating), this._activate(r === this.options.active ? !1 : r), void 0;
                    default:
                        return
                    }
                    t.preventDefault(), clearTimeout(this.activating), r = this._focusNextTab(r, i), t.ctrlKey || (n.attr("aria-selected", "false"), this.tabs.eq(r).attr("aria-selected", "true"), this.activating = this._delay(function () {
                        this.option("active", r)
                    }, this.delay))
                }
            },
            _panelKeydown: function (t) {
                this._handlePageNav(t) || t.ctrlKey && t.keyCode === e.ui.keyCode.UP && (t.preventDefault(), this.active.focus())
            },
            _handlePageNav: function (t) {
                return t.altKey && t.keyCode === e.ui.keyCode.PAGE_UP ? (this._activate(this._focusNextTab(this.options.active - 1, !1)), !0) : t.altKey && t.keyCode === e.ui.keyCode.PAGE_DOWN ? (this._activate(this._focusNextTab(this.options.active + 1, !0)), !0) : void 0
            },
            _findNextTab: function (t, n) {
                function i() {
                    return t > r && (t = 0), 0 > t && (t = r), t
                }
                for (var r = this.tabs.length - 1; - 1 !== e.inArray(i(), this.options.disabled);) t = n ? t + 1 : t - 1;
                return t
            },
            _focusNextTab: function (e, t) {
                return e = this._findNextTab(e, t), this.tabs.eq(e).focus(), e
            },
            _setOption: function (e, t) {
                return "active" === e ? (this._activate(t), void 0) : "disabled" === e ? (this._setupDisabled(t), void 0) : (this._super(e, t), "collapsible" === e && (this.element.toggleClass("ui-tabs-collapsible", t), !t && this.options.active === !1 && this._activate(0)), "event" === e && this._setupEvents(t), "heightStyle" === e && this._setupHeightStyle(t), void 0)
            },
            _tabId: function (e) {
                return e.attr("aria-controls") || "ui-tabs-" + i()
            },
            _sanitizeSelector: function (e) {
                return e ? e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&") : ""
            },
            refresh: function () {
                var t = this.options,
                    n = this.tablist.children(":has(a[href])");
                t.disabled = e.map(n.filter(".ui-state-disabled"), function (e) {
                    return n.index(e)
                }), this._processTabs(), t.active !== !1 && this.anchors.length ? this.active.length && !e.contains(this.tablist[0], this.active[0]) ? this.tabs.length === t.disabled.length ? (t.active = !1, this.active = e()) : this._activate(this._findNextTab(Math.max(0, t.active - 1), !1)) : t.active = this.tabs.index(this.active) : (t.active = !1, this.active = e()), this._refresh()
            },
            _refresh: function () {
                this._setupDisabled(this.options.disabled), this._setupEvents(this.options.event), this._setupHeightStyle(this.options.heightStyle), this.tabs.not(this.active).attr({
                    "aria-selected": "false",
                    tabIndex: -1
                }), this.panels.not(this._getPanelForTab(this.active)).hide().attr({
                    "aria-expanded": "false",
                    "aria-hidden": "true"
                }), this.active.length ? (this.active.addClass("ui-tabs-active ui-state-active").attr({
                    "aria-selected": "true",
                    tabIndex: 0
                }), this._getPanelForTab(this.active).show().attr({
                    "aria-expanded": "true",
                    "aria-hidden": "false"
                })) : this.tabs.eq(0).attr("tabIndex", 0)
            },
            _processTabs: function () {
                var t = this;
                this.tablist = this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role", "tablist"), this.tabs = this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({
                    role: "tab",
                    tabIndex: -1
                }), this.anchors = this.tabs.map(function () {
                    return e("a", this)[0]
                }).addClass("ui-tabs-anchor").attr({
                    role: "presentation",
                    tabIndex: -1
                }), this.panels = e(), this.anchors.each(function (n, r) {
                    var i, o, u, a = e(r).uniqueId().attr("id"),
                        f = e(r).closest("li"),
                        l = f.attr("aria-controls");
                    s(r) ? (i = r.hash, o = t.element.find(t._sanitizeSelector(i))) : (u = t._tabId(f), i = "#" + u, o = t.element.find(i), o.length || (o = t._createPanel(u), o.insertAfter(t.panels[n - 1] || t.tablist)), o.attr("aria-live", "polite")), o.length && (t.panels = t.panels.add(o)), l && f.data("ui-tabs-aria-controls", l), f.attr({
                        "aria-controls": i.substring(1),
                        "aria-labelledby": a
                    }), o.attr("aria-labelledby", a)
                }), this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role", "tabpanel")
            },
            _getList: function () {
                return this.element.find("ol,ul").eq(0)
            },
            _createPanel: function (t) {
                return e("<div>").attr("id", t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy", !0)
            },
            _setupDisabled: function (t) {
                e.isArray(t) && (t.length ? t.length === this.anchors.length && (t = !0) : t = !1);
                for (var r, n = 0; r = this.tabs[n]; n++) t === !0 || -1 !== e.inArray(n, t) ? e(r).addClass("ui-state-disabled").attr("aria-disabled", "true") : e(r).removeClass("ui-state-disabled").removeAttr("aria-disabled");
                this.options.disabled = t
            },
            _setupEvents: function (t) {
                var n = {
                    click: function (e) {
                        e.preventDefault()
                    }
                };
                t && e.each(t.split(" "), function (e, t) {
                    n[t] = "_eventHandler"
                }), this._off(this.anchors.add(this.tabs).add(this.panels)), this._on(this.anchors, n), this._on(this.tabs, {
                    keydown: "_tabKeydown"
                }), this._on(this.panels, {
                    keydown: "_panelKeydown"
                }), this._focusable(this.tabs), this._hoverable(this.tabs)
            },
            _setupHeightStyle: function (t) {
                var n, r = this.element.parent();
                "fill" === t ? (n = r.height(), n -= this.element.outerHeight() - this.element.height(), this.element.siblings(":visible").each(function () {
                    var t = e(this),
                        r = t.css("position");
                    "absolute" !== r && "fixed" !== r && (n -= t.outerHeight(!0))
                }), this.element.children().not(this.panels).each(function () {
                    n -= e(this).outerHeight(!0)
                }), this.panels.each(function () {
                    e(this).height(Math.max(0, n - e(this).innerHeight() + e(this).height()))
                }).css("overflow", "auto")) : "auto" === t && (n = 0, this.panels.each(function () {
                    n = Math.max(n, e(this).height("").height())
                }).height(n))
            },
            _eventHandler: function (t) {
                var n = this.options,
                    r = this.active,
                    i = e(t.currentTarget),
                    s = i.closest("li"),
                    o = s[0] === r[0],
                    u = o && n.collapsible,
                    a = u ? e() : this._getPanelForTab(s),
                    f = r.length ? this._getPanelForTab(r) : e(),
                    l = {
                        oldTab: r,
                        oldPanel: f,
                        newTab: u ? e() : s,
                        newPanel: a
                    };
                t.preventDefault(), s.hasClass("ui-state-disabled") || s.hasClass("ui-tabs-loading") || this.running || o && !n.collapsible || this._trigger("beforeActivate", t, l) === !1 || (n.active = u ? !1 : this.tabs.index(s), this.active = o ? e() : s, this.xhr && this.xhr.abort(), !f.length && !a.length && e.error("jQuery UI Tabs: Mismatching fragment identifier."), a.length && this.load(this.tabs.index(s), t), this._toggle(t, l))
            },
            _toggle: function (t, n) {
                function o() {
                    r.running = !1, r._trigger("activate", t, n)
                }

                function u() {
                    n.newTab.closest("li").addClass("ui-tabs-active ui-state-active"), i.length && r.options.show ? r._show(i, r.options.show, o) : (i.show(), o())
                }
                var r = this,
                    i = n.newPanel,
                    s = n.oldPanel;
                this.running = !0, s.length && this.options.hide ? this._hide(s, this.options.hide, function () {
                    n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"), u()
                }) : (n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"), s.hide(), u()), s.attr({
                    "aria-expanded": "false",
                    "aria-hidden": "true"
                }), n.oldTab.attr("aria-selected", "false"), i.length && s.length ? n.oldTab.attr("tabIndex", -1) : i.length && this.tabs.filter(function () {
                    return 0 === e(this).attr("tabIndex")
                }).attr("tabIndex", -1), i.attr({
                    "aria-expanded": "true",
                    "aria-hidden": "false"
                }), n.newTab.attr({
                    "aria-selected": "true",
                    tabIndex: 0
                })
            },
            _activate: function (t) {
                var n, r = this._findActive(t);
                r[0] !== this.active[0] && (r.length || (r = this.active), n = r.find(".ui-tabs-anchor")[0], this._eventHandler({
                    target: n,
                    currentTarget: n,
                    preventDefault: e.noop
                }))
            },
            _findActive: function (t) {
                return t === !1 ? e() : this.tabs.eq(t)
            },
            _getIndex: function (e) {
                return "string" == typeof e && (e = this.anchors.index(this.anchors.filter("[href$='" + e + "']"))), e
            },
            _destroy: function () {
                this.xhr && this.xhr.abort(), this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"), this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"), this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(), this.tabs.add(this.panels).each(function () {
                    e.data(this, "ui-tabs-destroy") ? e(this).remove() : e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")
                }), this.tabs.each(function () {
                    var t = e(this),
                        n = t.data("ui-tabs-aria-controls");
                    n ? t.attr("aria-controls", n).removeData("ui-tabs-aria-controls") : t.removeAttr("aria-controls")
                }), this.panels.show(), "content" !== this.options.heightStyle && this.panels.css("height", "")
            },
            enable: function (n) {
                var r = this.options.disabled;
                r !== !1 && (n === t ? r = !1 : (n = this._getIndex(n), r = e.isArray(r) ? e.map(r, function (e) {
                    return e !== n ? e : null
                }) : e.map(this.tabs, function (e, t) {
                    return t !== n ? t : null
                })), this._setupDisabled(r))
            },
            disable: function (n) {
                var r = this.options.disabled;
                if (r !== !0) {
                    if (n === t) r = !0;
                    else {
                        if (n = this._getIndex(n), -1 !== e.inArray(n, r)) return;
                        r = e.isArray(r) ? e.merge([n], r).sort() : [n]
                    }
                    this._setupDisabled(r)
                }
            },
            load: function (t, n) {
                t = this._getIndex(t);
                var r = this,
                    i = this.tabs.eq(t),
                    o = i.find(".ui-tabs-anchor"),
                    u = this._getPanelForTab(i),
                    a = {
                        tab: i,
                        panel: u
                    };
                s(o[0]) || (this.xhr = e.ajax(this._ajaxSettings(o, n, a)), this.xhr && "canceled" !== this.xhr.statusText && (i.addClass("ui-tabs-loading"), u.attr("aria-busy", "true"), this.xhr.success(function (e) {
                    setTimeout(function () {
                        u.html(e), r._trigger("load", n, a)
                    }, 1)
                }).complete(function (e, t) {
                    setTimeout(function () {
                        "abort" === t && r.panels.stop(!1, !0), i.removeClass("ui-tabs-loading"), u.removeAttr("aria-busy"), e === r.xhr && delete r.xhr
                    }, 1)
                })))
            },
            _ajaxSettings: function (t, n, r) {
                var i = this;
                return {
                    url: t.attr("href"),
                    beforeSend: function (t, s) {
                        return i._trigger("beforeLoad", n, e.extend({
                            jqXHR: t,
                            ajaxSettings: s
                        }, r))
                    }
                }
            },
            _getPanelForTab: function (t) {
                var n = e(t).attr("aria-controls");
                return this.element.find(this._sanitizeSelector("#" + n))
            }
        })
    }(e),
    function () {}(e)
}),
function (q, r, m) {
    var s = {
            required: "The %s field is required.",
            matches: "The %s field does not match the %s field.",
            "default": "The %s field is still set to default, please change.",
            valid_email: "The %s field must contain a valid email address.",
            valid_emails: "The %s field must contain all valid email addresses.",
            min_length: "The %s field must be at least %s characters in length.",
            max_length: "The %s field must not exceed %s characters in length.",
            exact_length: "The %s field must be exactly %s characters in length.",
            greater_than: "The %s field must contain a number greater than %s.",
            less_than: "The %s field must contain a number less than %s.",
            alpha: "The %s field must only contain alphabetical characters.",
            alpha_numeric: "The %s field must only contain alpha-numeric characters.",
            alpha_dash: "The %s field must only contain alpha-numeric characters, underscores, and dashes.",
            numeric: "The %s field must contain only numbers.",
            integer: "The %s field must contain an integer.",
            decimal: "The %s field must contain a decimal number.",
            is_natural: "The %s field must contain only positive numbers.",
            is_natural_no_zero: "The %s field must contain a number greater than zero.",
            valid_ip: "The %s field must contain a valid IP.",
            valid_base64: "The %s field must contain a base64 string.",
            valid_credit_card: "The %s field must contain a valid credit card number.",
            is_file_type: "The %s field must contain only %s files.",
            valid_url: "The %s field must contain a valid URL."
        },
        t = function () {},
        u = /^(.+?)\[(.+)\]$/,
        h = /^[0-9]+$/,
        v = /^\-?[0-9]+$/,
        k = /^\-?[0-9]*\.?[0-9]+$/,
        p = /^[a-zA-Z0-9.!#$%&amp;'*+\-\/=?\^_`{|}~\-]+@[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*$/,
        w = /^[a-z]+$/i,
        x = /^[a-z0-9]+$/i,
        y = /^[a-z0-9_\-]+$/i,
        z = /^[0-9]+$/i,
        A = /^[1-9][0-9]*$/i,
        B = /^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})$/i,
        C = /[^a-zA-Z0-9\/\+=]/i,
        D = /^[\d\-\s]+$/,
        E = /^((http|https):\/\/(\w+:{0,1}\w*@)?(\S+)|)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,
        e = function (a, b, c) {
            for (this.callback = c || t, this.errors = [], this.fields = {}, this.form = this._formByNameOrNode(a) || {}, this.messages = {}, this.handlers = {}, a = 0, c = b.length; c > a; a++) {
                var d = b[a];
                if ((d.name || d.names) && d.rules)
                    if (d.names)
                        for (var l = 0; l < d.names.length; l++) this._addField(d, d.names[l]);
                    else this._addField(d, d.name)
            }
            var g = this.form.onsubmit;
            this.form.onsubmit = function (a) {
                return function (b) {
                    try {
                        return a._validateForm(b) && (g === m || g())
                    } catch (c) {}
                }
            }(this)
        },
        n = function (a, b) {
            var c;
            if (!(0 < a.length) || "radio" !== a[0].type && "checkbox" !== a[0].type) return a[b];
            for (c = 0; c < a.length; c++)
                if (a[c].checked) return a[c][b]
        };
    e.prototype.setMessage = function (a, b) {
        return this.messages[a] = b, this
    }, e.prototype.registerCallback = function (a, b) {
        return a && "string" == typeof a && b && "function" == typeof b && (this.handlers[a] = b), this
    }, e.prototype._formByNameOrNode = function (a) {
        return "object" == typeof a ? a : r.forms[a]
    }, e.prototype._addField = function (a, b) {
        this.fields[b] = {
            name: b,
            display: a.display || b,
            rules: a.rules,
            id: null,
            type: null,
            value: null,
            checked: null
        }
    }, e.prototype._validateForm = function (a) {
        this.errors = [];
        for (var b in this.fields)
            if (this.fields.hasOwnProperty(b)) {
                var c = this.fields[b] || {},
                    d = this.form[c.name];
                d && d !== m && (c.id = n(d, "id"), c.type = 0 < d.length ? d[0].type : d.type, c.value = n(d, "value"), c.checked = n(d, "checked"), this._validateField(c))
            }
        return "function" == typeof this.callback && this.callback(this.errors, a), 0 < this.errors.length && (a && a.preventDefault ? a.preventDefault() : event && (event.returnValue = !1)), !0
    }, e.prototype._validateField = function (a) {
        for (var b = a.rules.split("|"), c = a.rules.indexOf("required"), d = !a.value || "" === a.value || a.value === m, l = 0, g = b.length; g > l; l++) {
            var f = b[l],
                e = null,
                h = !1,
                k = u.exec(f);
            if ((-1 !== c || -1 !== f.indexOf("!callback_") || !d) && (k && (f = k[1], e = k[2]), "!" === f.charAt(0) && (f = f.substring(1, f.length)), "function" == typeof this._hooks[f] ? this._hooks[f].apply(this, [a, e]) || (h = !0) : "callback_" === f.substring(0, 9) && (f = f.substring(9, f.length), "function" == typeof this.handlers[f] && !1 === this.handlers[f].apply(this, [a.value, e]) && (h = !0)), h)) {
                b = this.messages[f] || s[f], c = "An error has occurred with the " + a.display + " field.", b && (c = b.replace("%s", a.display), e && (c = c.replace("%s", this.fields[e] ? this.fields[e].display : e))), this.errors.push({
                    id: a.id,
                    name: a.name,
                    message: c,
                    rule: f
                });
                break
            }
        }
    }, e.prototype._hooks = {
        required: function (a) {
            var b = a.value;
            return "checkbox" === a.type || "radio" === a.type ? !0 === a.checked : null !== b && "" !== b
        },
        "default": function (a, b) {
            return a.value !== b
        },
        matches: function (a, b) {
            var c = this.form[b];
            return c ? a.value === c.value : !1
        },
        valid_email: function (a) {
            return p.test(a.value)
        },
        valid_emails: function (a) {
            a = a.value.split(",");
            for (var b = 0; b < a.length; b++)
                if (!p.test(a[b])) return !1;
            return !0
        },
        min_length: function (a, b) {
            return h.test(b) ? a.value.length >= parseInt(b, 10) : !1
        },
        max_length: function (a, b) {
            return h.test(b) ? a.value.length <= parseInt(b, 10) : !1
        },
        exact_length: function (a, b) {
            return h.test(b) ? a.value.length === parseInt(b, 10) : !1
        },
        greater_than: function (a, b) {
            return k.test(a.value) ? parseFloat(a.value) > parseFloat(b) : !1
        },
        less_than: function (a, b) {
            return k.test(a.value) ? parseFloat(a.value) < parseFloat(b) : !1
        },
        alpha: function (a) {
            return w.test(a.value)
        },
        alpha_numeric: function (a) {
            return x.test(a.value)
        },
        alpha_dash: function (a) {
            return y.test(a.value)
        },
        numeric: function (a) {
            return h.test(a.value)
        },
        integer: function (a) {
            return v.test(a.value)
        },
        decimal: function (a) {
            return k.test(a.value)
        },
        is_natural: function (a) {
            return z.test(a.value)
        },
        is_natural_no_zero: function (a) {
            return A.test(a.value)
        },
        valid_ip: function (a) {
            return B.test(a.value)
        },
        valid_base64: function (a) {
            return C.test(a.value)
        },
        valid_url: function (a) {
            return E.test(a.value)
        },
        valid_credit_card: function (a) {
            if (!D.test(a.value)) return !1;
            var b = 0,
                c = 0,
                d = !1;
            a = a.value.replace(/\D/g, "");
            for (var e = a.length - 1; e >= 0; e--) c = a.charAt(e), c = parseInt(c, 10), d && 9 < (c *= 2) && (c -= 9), b += c, d = !d;
            return 0 === b % 10
        },
        is_file_type: function (a, b) {
            if ("file" !== a.type) return !0;
            var c = a.value.substr(a.value.lastIndexOf(".") + 1),
                d = b.split(","),
                e = !1,
                g = 0,
                f = d.length;
            for (g; f > g; g++) c == d[g] && (e = !0);
            return e
        }
    }, q.FormValidator = e
}(window, document);
var CryptoJS = CryptoJS || function (s, p) {
    var m = {},
        l = m.lib = {},
        n = function () {},
        r = l.Base = {
            extend: function (b) {
                n.prototype = this;
                var h = new n;
                return b && h.mixIn(b), h.hasOwnProperty("init") || (h.init = function () {
                    h.$super.init.apply(this, arguments)
                }), h.init.prototype = h, h.$super = this, h
            },
            create: function () {
                var b = this.extend();
                return b.init.apply(b, arguments), b
            },
            init: function () {},
            mixIn: function (b) {
                for (var h in b) b.hasOwnProperty(h) && (this[h] = b[h]);
                b.hasOwnProperty("toString") && (this.toString = b.toString)
            },
            clone: function () {
                return this.init.prototype.extend(this)
            }
        },
        q = l.WordArray = r.extend({
            init: function (b, h) {
                b = this.words = b || [], this.sigBytes = h != p ? h : 4 * b.length
            },
            toString: function (b) {
                return (b || t).stringify(this)
            },
            concat: function (b) {
                var h = this.words,
                    a = b.words,
                    j = this.sigBytes;
                if (b = b.sigBytes, this.clamp(), j % 4)
                    for (var g = 0; b > g; g++) h[j + g >>> 2] |= (255 & a[g >>> 2] >>> 24 - 8 * (g % 4)) << 24 - 8 * ((j + g) % 4);
                else if (65535 < a.length)
                    for (g = 0; b > g; g += 4) h[j + g >>> 2] = a[g >>> 2];
                else h.push.apply(h, a);
                return this.sigBytes += b, this
            },
            clamp: function () {
                var b = this.words,
                    h = this.sigBytes;
                b[h >>> 2] &= 4294967295 << 32 - 8 * (h % 4), b.length = s.ceil(h / 4)
            },
            clone: function () {
                var b = r.clone.call(this);
                return b.words = this.words.slice(0), b
            },
            random: function (b) {
                for (var h = [], a = 0; b > a; a += 4) h.push(0 | 4294967296 * s.random());
                return new q.init(h, b)
            }
        }),
        v = m.enc = {},
        t = v.Hex = {
            stringify: function (b) {
                var a = b.words;
                b = b.sigBytes;
                for (var g = [], j = 0; b > j; j++) {
                    var k = 255 & a[j >>> 2] >>> 24 - 8 * (j % 4);
                    g.push((k >>> 4).toString(16)), g.push((15 & k).toString(16))
                }
                return g.join("")
            },
            parse: function (b) {
                for (var a = b.length, g = [], j = 0; a > j; j += 2) g[j >>> 3] |= parseInt(b.substr(j, 2), 16) << 24 - 4 * (j % 8);
                return new q.init(g, a / 2)
            }
        },
        a = v.Latin1 = {
            stringify: function (b) {
                var a = b.words;
                b = b.sigBytes;
                for (var g = [], j = 0; b > j; j++) g.push(String.fromCharCode(255 & a[j >>> 2] >>> 24 - 8 * (j % 4)));
                return g.join("")
            },
            parse: function (b) {
                for (var a = b.length, g = [], j = 0; a > j; j++) g[j >>> 2] |= (255 & b.charCodeAt(j)) << 24 - 8 * (j % 4);
                return new q.init(g, a)
            }
        },
        u = v.Utf8 = {
            stringify: function (b) {
                try {
                    return decodeURIComponent(escape(a.stringify(b)))
                } catch (g) {
                    throw Error("Malformed UTF-8 data")
                }
            },
            parse: function (b) {
                return a.parse(unescape(encodeURIComponent(b)))
            }
        },
        g = l.BufferedBlockAlgorithm = r.extend({
            reset: function () {
                this._data = new q.init, this._nDataBytes = 0
            },
            _append: function (b) {
                "string" == typeof b && (b = u.parse(b)), this._data.concat(b), this._nDataBytes += b.sigBytes
            },
            _process: function (b) {
                var a = this._data,
                    g = a.words,
                    j = a.sigBytes,
                    k = this.blockSize,
                    m = j / (4 * k),
                    m = b ? s.ceil(m) : s.max((0 | m) - this._minBufferSize, 0);
                if (b = m * k, j = s.min(4 * b, j), b) {
                    for (var l = 0; b > l; l += k) this._doProcessBlock(g, l);
                    l = g.splice(0, b), a.sigBytes -= j
                }
                return new q.init(l, j)
            },
            clone: function () {
                var b = r.clone.call(this);
                return b._data = this._data.clone(), b
            },
            _minBufferSize: 0
        });
    l.Hasher = g.extend({
        cfg: r.extend(),
        init: function (b) {
            this.cfg = this.cfg.extend(b), this.reset()
        },
        reset: function () {
            g.reset.call(this), this._doReset()
        },
        update: function (b) {
            return this._append(b), this._process(), this
        },
        finalize: function (b) {
            return b && this._append(b), this._doFinalize()
        },
        blockSize: 16,
        _createHelper: function (b) {
            return function (a, g) {
                return new b.init(g).finalize(a)
            }
        },
        _createHmacHelper: function (b) {
            return function (a, g) {
                return new k.HMAC.init(b, g).finalize(a)
            }
        }
    });
    var k = m.algo = {};
    return m
}(Math);
! function (s) {
    function p(a, k, b, h, l, j, m) {
        return a = a + (k & b | ~k & h) + l + m, (a << j | a >>> 32 - j) + k
    }

    function m(a, k, b, h, l, j, m) {
        return a = a + (k & h | b & ~h) + l + m, (a << j | a >>> 32 - j) + k
    }

    function l(a, k, b, h, l, j, m) {
        return a = a + (k ^ b ^ h) + l + m, (a << j | a >>> 32 - j) + k
    }

    function n(a, k, b, h, l, j, m) {
        return a = a + (b ^ (k | ~h)) + l + m, (a << j | a >>> 32 - j) + k
    }
    for (var r = CryptoJS, q = r.lib, v = q.WordArray, t = q.Hasher, q = r.algo, a = [], u = 0; 64 > u; u++) a[u] = 0 | 4294967296 * s.abs(s.sin(u + 1));
    q = q.MD5 = t.extend({
        _doReset: function () {
            this._hash = new v.init([1732584193, 4023233417, 2562383102, 271733878])
        },
        _doProcessBlock: function (g, k) {
            for (var b = 0; 16 > b; b++) {
                var h = k + b,
                    w = g[h];
                g[h] = 16711935 & (w << 8 | w >>> 24) | 4278255360 & (w << 24 | w >>> 8)
            }
            var b = this._hash.words,
                h = g[k + 0],
                w = g[k + 1],
                j = g[k + 2],
                q = g[k + 3],
                r = g[k + 4],
                s = g[k + 5],
                t = g[k + 6],
                u = g[k + 7],
                v = g[k + 8],
                x = g[k + 9],
                y = g[k + 10],
                z = g[k + 11],
                A = g[k + 12],
                B = g[k + 13],
                C = g[k + 14],
                D = g[k + 15],
                c = b[0],
                d = b[1],
                e = b[2],
                f = b[3],
                c = p(c, d, e, f, h, 7, a[0]),
                f = p(f, c, d, e, w, 12, a[1]),
                e = p(e, f, c, d, j, 17, a[2]),
                d = p(d, e, f, c, q, 22, a[3]),
                c = p(c, d, e, f, r, 7, a[4]),
                f = p(f, c, d, e, s, 12, a[5]),
                e = p(e, f, c, d, t, 17, a[6]),
                d = p(d, e, f, c, u, 22, a[7]),
                c = p(c, d, e, f, v, 7, a[8]),
                f = p(f, c, d, e, x, 12, a[9]),
                e = p(e, f, c, d, y, 17, a[10]),
                d = p(d, e, f, c, z, 22, a[11]),
                c = p(c, d, e, f, A, 7, a[12]),
                f = p(f, c, d, e, B, 12, a[13]),
                e = p(e, f, c, d, C, 17, a[14]),
                d = p(d, e, f, c, D, 22, a[15]),
                c = m(c, d, e, f, w, 5, a[16]),
                f = m(f, c, d, e, t, 9, a[17]),
                e = m(e, f, c, d, z, 14, a[18]),
                d = m(d, e, f, c, h, 20, a[19]),
                c = m(c, d, e, f, s, 5, a[20]),
                f = m(f, c, d, e, y, 9, a[21]),
                e = m(e, f, c, d, D, 14, a[22]),
                d = m(d, e, f, c, r, 20, a[23]),
                c = m(c, d, e, f, x, 5, a[24]),
                f = m(f, c, d, e, C, 9, a[25]),
                e = m(e, f, c, d, q, 14, a[26]),
                d = m(d, e, f, c, v, 20, a[27]),
                c = m(c, d, e, f, B, 5, a[28]),
                f = m(f, c, d, e, j, 9, a[29]),
                e = m(e, f, c, d, u, 14, a[30]),
                d = m(d, e, f, c, A, 20, a[31]),
                c = l(c, d, e, f, s, 4, a[32]),
                f = l(f, c, d, e, v, 11, a[33]),
                e = l(e, f, c, d, z, 16, a[34]),
                d = l(d, e, f, c, C, 23, a[35]),
                c = l(c, d, e, f, w, 4, a[36]),
                f = l(f, c, d, e, r, 11, a[37]),
                e = l(e, f, c, d, u, 16, a[38]),
                d = l(d, e, f, c, y, 23, a[39]),
                c = l(c, d, e, f, B, 4, a[40]),
                f = l(f, c, d, e, h, 11, a[41]),
                e = l(e, f, c, d, q, 16, a[42]),
                d = l(d, e, f, c, t, 23, a[43]),
                c = l(c, d, e, f, x, 4, a[44]),
                f = l(f, c, d, e, A, 11, a[45]),
                e = l(e, f, c, d, D, 16, a[46]),
                d = l(d, e, f, c, j, 23, a[47]),
                c = n(c, d, e, f, h, 6, a[48]),
                f = n(f, c, d, e, u, 10, a[49]),
                e = n(e, f, c, d, C, 15, a[50]),
                d = n(d, e, f, c, s, 21, a[51]),
                c = n(c, d, e, f, A, 6, a[52]),
                f = n(f, c, d, e, q, 10, a[53]),
                e = n(e, f, c, d, y, 15, a[54]),
                d = n(d, e, f, c, w, 21, a[55]),
                c = n(c, d, e, f, v, 6, a[56]),
                f = n(f, c, d, e, D, 10, a[57]),
                e = n(e, f, c, d, t, 15, a[58]),
                d = n(d, e, f, c, B, 21, a[59]),
                c = n(c, d, e, f, r, 6, a[60]),
                f = n(f, c, d, e, z, 10, a[61]),
                e = n(e, f, c, d, j, 15, a[62]),
                d = n(d, e, f, c, x, 21, a[63]);
            b[0] = 0 | b[0] + c, b[1] = 0 | b[1] + d, b[2] = 0 | b[2] + e, b[3] = 0 | b[3] + f
        },
        _doFinalize: function () {
            var a = this._data,
                k = a.words,
                b = 8 * this._nDataBytes,
                h = 8 * a.sigBytes;
            k[h >>> 5] |= 128 << 24 - h % 32;
            var l = s.floor(b / 4294967296);
            for (k[(h + 64 >>> 9 << 4) + 15] = 16711935 & (l << 8 | l >>> 24) | 4278255360 & (l << 24 | l >>> 8), k[(h + 64 >>> 9 << 4) + 14] = 16711935 & (b << 8 | b >>> 24) | 4278255360 & (b << 24 | b >>> 8), a.sigBytes = 4 * (k.length + 1), this._process(), a = this._hash, k = a.words, b = 0; 4 > b; b++) h = k[b], k[b] = 16711935 & (h << 8 | h >>> 24) | 4278255360 & (h << 24 | h >>> 8);
            return a
        },
        clone: function () {
            var a = t.clone.call(this);
            return a._hash = this._hash.clone(), a
        }
    }), r.MD5 = t._createHelper(q), r.HmacMD5 = t._createHmacHelper(q)
}(Math),
function ($) {
    $.InFieldLabels = function (b, c, d) {
        var f = this;
        f.$label = $(b), f.label = b, f.$field = $(c), f.field = c, f.$label.data("InFieldLabels", f), f.showing = !0, f.init = function () {
            f.options = $.extend({}, $.InFieldLabels.defaultOptions, d), "" != f.$field.val() && (f.$label.hide(), f.showing = !1), f.$field.focus(function () {
                f.fadeOnFocus()
            }).blur(function () {
                f.checkForEmpty(!0)
            }).bind("keydown.infieldlabel", function (e) {
                f.hideOnChange(e)
            }).change(function () {
                f.checkForEmpty()
            }).bind("onPropertyChange", function () {
                f.checkForEmpty()
            })
        }, f.fadeOnFocus = function () {
            f.showing && f.setOpacity(f.options.fadeOpacity)
        }, f.setOpacity = function (a) {
            f.$label.stop().animate({
                opacity: a
            }, f.options.fadeDuration), f.showing = a > 0
        }, f.checkForEmpty = function (a) {
            "" == f.$field.val() ? (f.prepForShow(), f.setOpacity(a ? 1 : f.options.fadeOpacity)) : f.setOpacity(0)
        }, f.prepForShow = function () {
            f.showing || (f.$label.css({
                opacity: 0
            }).show(), f.$field.bind("keydown.infieldlabel", function (e) {
                f.hideOnChange(e)
            }))
        }, f.hideOnChange = function (e) {
            16 != e.keyCode && 9 != e.keyCode && (f.showing && (f.$label.hide(), f.showing = !1), f.$field.unbind("keydown.infieldlabel"))
        }, f.init()
    }, $.InFieldLabels.defaultOptions = {
        fadeOpacity: .5,
        fadeDuration: 300
    }, $.fn.inFieldLabels = function (c) {
        return this.each(function () {
            var a = $(this).attr("for");
            if (a) {
                var b = $("input#" + a + "[type='text'],input#" + a + "[type='password'],textarea#" + a);
                0 != b.length && new $.InFieldLabels(this, b[0], c)
            }
        })
    }
}(jQuery),
function (q, r, m) {
    var s = {
            required: "The %s field is required.",
            matches: "The %s field does not match the %s field.",
            "default": "The %s field is still set to default, please change.",
            valid_email: "The %s field must contain a valid email address.",
            valid_emails: "The %s field must contain all valid email addresses.",
            min_length: "The %s field must be at least %s characters in length.",
            max_length: "The %s field must not exceed %s characters in length.",
            exact_length: "The %s field must be exactly %s characters in length.",
            greater_than: "The %s field must contain a number greater than %s.",
            less_than: "The %s field must contain a number less than %s.",
            alpha: "The %s field must only contain alphabetical characters.",
            alpha_numeric: "The %s field must only contain alpha-numeric characters.",
            alpha_dash: "The %s field must only contain alpha-numeric characters, underscores, and dashes.",
            numeric: "The %s field must contain only numbers.",
            integer: "The %s field must contain an integer.",
            decimal: "The %s field must contain a decimal number.",
            is_natural: "The %s field must contain only positive numbers.",
            is_natural_no_zero: "The %s field must contain a number greater than zero.",
            valid_ip: "The %s field must contain a valid IP.",
            valid_base64: "The %s field must contain a base64 string.",
            valid_credit_card: "The %s field must contain a valid credit card number.",
            is_file_type: "The %s field must contain only %s files.",
            valid_url: "The %s field must contain a valid URL."
        },
        t = function () {},
        u = /^(.+?)\[(.+)\]$/,
        h = /^[0-9]+$/,
        v = /^\-?[0-9]+$/,
        k = /^\-?[0-9]*\.?[0-9]+$/,
        p = /^[a-zA-Z0-9.!#$%&amp;'*+\-\/=?\^_`{|}~\-]+@[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*$/,
        w = /^[a-z]+$/i,
        x = /^[a-z0-9]+$/i,
        y = /^[a-z0-9_\-]+$/i,
        z = /^[0-9]+$/i,
        A = /^[1-9][0-9]*$/i,
        B = /^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})$/i,
        C = /[^a-zA-Z0-9\/\+=]/i,
        D = /^[\d\-\s]+$/,
        E = /^((http|https):\/\/(\w+:{0,1}\w*@)?(\S+)|)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,
        e = function (a, b, c) {
            for (this.callback = c || t, this.errors = [], this.fields = {}, this.form = this._formByNameOrNode(a) || {}, this.messages = {}, this.handlers = {}, a = 0, c = b.length; c > a; a++) {
                var d = b[a];
                if ((d.name || d.names) && d.rules)
                    if (d.names)
                        for (var l = 0; l < d.names.length; l++) this._addField(d, d.names[l]);
                    else this._addField(d, d.name)
            }
            var g = this.form.onsubmit;
            this.form.onsubmit = function (a) {
                return function (b) {
                    try {
                        return a._validateForm(b) && (g === m || g())
                    } catch (c) {}
                }
            }(this)
        },
        n = function (a, b) {
            var c;
            if (!(0 < a.length) || "radio" !== a[0].type && "checkbox" !== a[0].type) return a[b];
            for (c = 0; c < a.length; c++)
                if (a[c].checked) return a[c][b]
        };
    e.prototype.setMessage = function (a, b) {
        return this.messages[a] = b, this
    }, e.prototype.registerCallback = function (a, b) {
        return a && "string" == typeof a && b && "function" == typeof b && (this.handlers[a] = b), this
    }, e.prototype._formByNameOrNode = function (a) {
        return "object" == typeof a ? a : r.forms[a]
    }, e.prototype._addField = function (a, b) {
        this.fields[b] = {
            name: b,
            display: a.display || b,
            rules: a.rules,
            id: null,
            type: null,
            value: null,
            checked: null
        }
    }, e.prototype._validateForm = function (a) {
        this.errors = [];
        for (var b in this.fields)
            if (this.fields.hasOwnProperty(b)) {
                var c = this.fields[b] || {},
                    d = this.form[c.name];
                d && d !== m && (c.id = n(d, "id"), c.type = 0 < d.length ? d[0].type : d.type, c.value = n(d, "value"), c.checked = n(d, "checked"), this._validateField(c))
            }
        return "function" == typeof this.callback && this.callback(this.errors, a), 0 < this.errors.length && (a && a.preventDefault ? a.preventDefault() : event && (event.returnValue = !1)), !0
    }, e.prototype._validateField = function (a) {
        for (var b = a.rules.split("|"), c = a.rules.indexOf("required"), d = !a.value || "" === a.value || a.value === m, l = 0, g = b.length; g > l; l++) {
            var f = b[l],
                e = null,
                h = !1,
                k = u.exec(f);
            if ((-1 !== c || -1 !== f.indexOf("!callback_") || !d) && (k && (f = k[1], e = k[2]), "!" === f.charAt(0) && (f = f.substring(1, f.length)), "function" == typeof this._hooks[f] ? this._hooks[f].apply(this, [a, e]) || (h = !0) : "callback_" === f.substring(0, 9) && (f = f.substring(9, f.length), "function" == typeof this.handlers[f] && !1 === this.handlers[f].apply(this, [a.value, e]) && (h = !0)), h)) {
                b = this.messages[f] || s[f], c = "An error has occurred with the " + a.display + " field.", b && (c = b.replace("%s", a.display), e && (c = c.replace("%s", this.fields[e] ? this.fields[e].display : e))), this.errors.push({
                    id: a.id,
                    name: a.name,
                    message: c,
                    rule: f
                });
                break
            }
        }
    }, e.prototype._hooks = {
        required: function (a) {
            var b = a.value;
            return "checkbox" === a.type || "radio" === a.type ? !0 === a.checked : null !== b && "" !== b
        },
        "default": function (a, b) {
            return a.value !== b
        },
        matches: function (a, b) {
            var c = this.form[b];
            return c ? a.value === c.value : !1
        },
        valid_email: function (a) {
            return p.test(a.value)
        },
        valid_emails: function (a) {
            a = a.value.split(",");
            for (var b = 0; b < a.length; b++)
                if (!p.test(a[b])) return !1;
            return !0
        },
        min_length: function (a, b) {
            return h.test(b) ? a.value.length >= parseInt(b, 10) : !1
        },
        max_length: function (a, b) {
            return h.test(b) ? a.value.length <= parseInt(b, 10) : !1
        },
        exact_length: function (a, b) {
            return h.test(b) ? a.value.length === parseInt(b, 10) : !1
        },
        greater_than: function (a, b) {
            return k.test(a.value) ? parseFloat(a.value) > parseFloat(b) : !1
        },
        less_than: function (a, b) {
            return k.test(a.value) ? parseFloat(a.value) < parseFloat(b) : !1
        },
        alpha: function (a) {
            return w.test(a.value)
        },
        alpha_numeric: function (a) {
            return x.test(a.value)
        },
        alpha_dash: function (a) {
            return y.test(a.value)
        },
        numeric: function (a) {
            return h.test(a.value)
        },
        integer: function (a) {
            return v.test(a.value)
        },
        decimal: function (a) {
            return k.test(a.value)
        },
        is_natural: function (a) {
            return z.test(a.value)
        },
        is_natural_no_zero: function (a) {
            return A.test(a.value)
        },
        valid_ip: function (a) {
            return B.test(a.value)
        },
        valid_base64: function (a) {
            return C.test(a.value)
        },
        valid_url: function (a) {
            return E.test(a.value)
        },
        valid_credit_card: function (a) {
            if (!D.test(a.value)) return !1;
            var b = 0,
                c = 0,
                d = !1;
            a = a.value.replace(/\D/g, "");
            for (var e = a.length - 1; e >= 0; e--) c = a.charAt(e), c = parseInt(c, 10), d && 9 < (c *= 2) && (c -= 9), b += c, d = !d;
            return 0 === b % 10
        },
        is_file_type: function (a, b) {
            if ("file" !== a.type) return !0;
            var c = a.value.substr(a.value.lastIndexOf(".") + 1),
                d = b.split(","),
                e = !1,
                g = 0,
                f = d.length;
            for (g; f > g; g++) c == d[g] && (e = !0);
            return e
        }
    }, q.FormValidator = e
}(window, document),
function ($) {
    $.Jcrop = function (obj, opt) {
        function px(n) {
            return Math.round(n) + "px"
        }

        function cssClass(cl) {
            return options.baseClass + "-" + cl
        }

        function supportsColorFade() {
            return $.fx.step.hasOwnProperty("backgroundColor")
        }

        function getPos(obj) {
            var pos = $(obj).offset();
            return [pos.left, pos.top]
        }

        function mouseAbs(e) {
            return [e.pageX - docOffset[0], e.pageY - docOffset[1]]
        }

        function setOptions(opt) {
            "object" != typeof opt && (opt = {}), options = $.extend(options, opt), $.each(["onChange", "onSelect", "onRelease", "onDblClick"], function (i, e) {
                "function" != typeof options[e] && (options[e] = function () {})
            })
        }

        function startDragMode(mode, pos, touch) {
            if (docOffset = getPos($img), Tracker.setCursor("move" === mode ? mode : mode + "-resize"), "move" === mode) return Tracker.activateHandlers(createMover(pos), doneSelect, touch);
            var fc = Coords.getFixed(),
                opp = oppLockCorner(mode),
                opc = Coords.getCorner(oppLockCorner(opp));
            Coords.setPressed(Coords.getCorner(opp)), Coords.setCurrent(opc), Tracker.activateHandlers(dragmodeHandler(mode, fc), doneSelect, touch)
        }

        function dragmodeHandler(mode, f) {
            return function (pos) {
                if (options.aspectRatio) switch (mode) {
                case "e":
                    pos[1] = f.y + 1;
                    break;
                case "w":
                    pos[1] = f.y + 1;
                    break;
                case "n":
                    pos[0] = f.x + 1;
                    break;
                case "s":
                    pos[0] = f.x + 1
                } else switch (mode) {
                case "e":
                    pos[1] = f.y2;
                    break;
                case "w":
                    pos[1] = f.y2;
                    break;
                case "n":
                    pos[0] = f.x2;
                    break;
                case "s":
                    pos[0] = f.x2
                }
                Coords.setCurrent(pos), Selection.update()
            }
        }

        function createMover(pos) {
            var lloc = pos;
            return KeyManager.watchKeys(),
                function (pos) {
                    Coords.moveOffset([pos[0] - lloc[0], pos[1] - lloc[1]]), lloc = pos, Selection.update()
                }
        }

        function oppLockCorner(ord) {
            switch (ord) {
            case "n":
                return "sw";
            case "s":
                return "nw";
            case "e":
                return "nw";
            case "w":
                return "ne";
            case "ne":
                return "sw";
            case "nw":
                return "se";
            case "se":
                return "nw";
            case "sw":
                return "ne"
            }
        }

        function createDragger(ord) {
            return function (e) {
                return options.disabled ? !1 : "move" !== ord || options.allowMove ? (docOffset = getPos($img), btndown = !0, startDragMode(ord, mouseAbs(e)), e.stopPropagation(), e.preventDefault(), !1) : !1
            }
        }

        function presize($obj, w, h) {
            var nw = $obj.width(),
                nh = $obj.height();
            nw > w && w > 0 && (nw = w, nh = w / $obj.width() * $obj.height()), nh > h && h > 0 && (nh = h, nw = h / $obj.height() * $obj.width()), xscale = $obj.width() / nw, yscale = $obj.height() / nh, $obj.width(nw).height(nh)
        }

        function unscale(c) {
            return {
                x: c.x * xscale,
                y: c.y * yscale,
                x2: c.x2 * xscale,
                y2: c.y2 * yscale,
                w: c.w * xscale,
                h: c.h * yscale
            }
        }

        function doneSelect() {
            var c = Coords.getFixed();
            c.w > options.minSelect[0] && c.h > options.minSelect[1] ? (Selection.enableHandles(), Selection.done()) : Selection.release(), Tracker.setCursor(options.allowSelect ? "crosshair" : "default")
        }

        function newSelection(e) {
            if (options.disabled) return !1;
            if (!options.allowSelect) return !1;
            btndown = !0, docOffset = getPos($img), Selection.disableHandles(), Tracker.setCursor("crosshair");
            var pos = mouseAbs(e);
            return Coords.setPressed(pos), Selection.update(), Tracker.activateHandlers(selectDrag, doneSelect, "touch" === e.type.substring(0, 5)), KeyManager.watchKeys(), e.stopPropagation(), e.preventDefault(), !1
        }

        function selectDrag(pos) {
            Coords.setCurrent(pos), Selection.update()
        }

        function newTracker() {
            var trk = $("<div></div>").addClass(cssClass("tracker"));
            return is_msie && trk.css({
                opacity: 0,
                backgroundColor: "white"
            }), trk
        }

        function setClass(cname) {
            $div.removeClass().addClass(cssClass("holder")).addClass(cname)
        }

        function animateTo(a, callback) {
            function queueAnimator() {
                window.setTimeout(animator, interv)
            }
            var x1 = a[0] / xscale,
                y1 = a[1] / yscale,
                x2 = a[2] / xscale,
                y2 = a[3] / yscale;
            if (!animating) {
                var animto = Coords.flipCoords(x1, y1, x2, y2),
                    c = Coords.getFixed(),
                    initcr = [c.x, c.y, c.x2, c.y2],
                    animat = initcr,
                    interv = options.animationDelay,
                    ix1 = animto[0] - initcr[0],
                    iy1 = animto[1] - initcr[1],
                    ix2 = animto[2] - initcr[2],
                    iy2 = animto[3] - initcr[3],
                    pcent = 0,
                    velocity = options.swingSpeed;
                x1 = animat[0], y1 = animat[1], x2 = animat[2], y2 = animat[3], Selection.animMode(!0);
                var animator = function () {
                    return function () {
                        pcent += (100 - pcent) / velocity, animat[0] = Math.round(x1 + pcent / 100 * ix1), animat[1] = Math.round(y1 + pcent / 100 * iy1), animat[2] = Math.round(x2 + pcent / 100 * ix2), animat[3] = Math.round(y2 + pcent / 100 * iy2), pcent >= 99.8 && (pcent = 100), 100 > pcent ? (setSelectRaw(animat), queueAnimator()) : (Selection.done(), Selection.animMode(!1), "function" == typeof callback && callback.call(api))
                    }
                }();
                queueAnimator()
            }
        }

        function setSelect(rect) {
            setSelectRaw([rect[0] / xscale, rect[1] / yscale, rect[2] / xscale, rect[3] / yscale]), options.onSelect.call(api, unscale(Coords.getFixed())), Selection.enableHandles()
        }

        function setSelectRaw(l) {
            Coords.setPressed([l[0], l[1]]), Coords.setCurrent([l[2], l[3]]), Selection.update()
        }

        function tellSelect() {
            return unscale(Coords.getFixed())
        }

        function tellScaled() {
            return Coords.getFixed()
        }

        function setOptionsNew(opt) {
            setOptions(opt), interfaceUpdate()
        }

        function disableCrop() {
            options.disabled = !0, Selection.disableHandles(), Selection.setCursor("default"), Tracker.setCursor("default")
        }

        function enableCrop() {
            options.disabled = !1, interfaceUpdate()
        }

        function cancelCrop() {
            Selection.done(), Tracker.activateHandlers(null, null)
        }

        function destroy() {
            $div.remove(), $origimg.show(), $origimg.css("visibility", "visible"), $(obj).removeData("Jcrop")
        }

        function setImage(src, callback) {
            Selection.release(), disableCrop();
            var img = new Image;
            img.onload = function () {
                var iw = img.width,
                    ih = img.height,
                    bw = options.boxWidth,
                    bh = options.boxHeight;
                $img.width(iw).height(ih), $img.attr("src", src), $img2.attr("src", src), presize($img, bw, bh), boundx = $img.width(), boundy = $img.height(), $img2.width(boundx).height(boundy), $trk.width(boundx + 2 * bound).height(boundy + 2 * bound), $div.width(boundx).height(boundy), Shade.resize(boundx, boundy), enableCrop(), "function" == typeof callback && callback.call(api)
            }, img.src = src
        }

        function colorChangeMacro($obj, color, now) {
            var mycolor = color || options.bgColor;
            options.bgFade && supportsColorFade() && options.fadeTime && !now ? $obj.animate({
                backgroundColor: mycolor
            }, {
                queue: !1,
                duration: options.fadeTime
            }) : $obj.css("backgroundColor", mycolor)
        }

        function interfaceUpdate(alt) {
            options.allowResize ? alt ? Selection.enableOnly() : Selection.enableHandles() : Selection.disableHandles(), Tracker.setCursor(options.allowSelect ? "crosshair" : "default"), Selection.setCursor(options.allowMove ? "move" : "default"), options.hasOwnProperty("trueSize") && (xscale = options.trueSize[0] / boundx, yscale = options.trueSize[1] / boundy), options.hasOwnProperty("setSelect") && (setSelect(options.setSelect), Selection.done(), delete options.setSelect), Shade.refresh(), options.bgColor != bgcolor && (colorChangeMacro(options.shade ? Shade.getShades() : $div, options.shade ? options.shadeColor || options.bgColor : options.bgColor), bgcolor = options.bgColor), bgopacity != options.bgOpacity && (bgopacity = options.bgOpacity, options.shade ? Shade.refresh() : Selection.setBgOpacity(bgopacity)), xlimit = options.maxSize[0] || 0, ylimit = options.maxSize[1] || 0, xmin = options.minSize[0] || 0, ymin = options.minSize[1] || 0, options.hasOwnProperty("outerImage") && ($img.attr("src", options.outerImage), delete options.outerImage), Selection.refresh()
        }
        var docOffset, options = $.extend({}, $.Jcrop.defaults),
            _ua = navigator.userAgent.toLowerCase(),
            is_msie = /msie/.test(_ua),
            ie6mode = /msie [1-6]\./.test(_ua);
        "object" != typeof obj && (obj = $(obj)[0]), "object" != typeof opt && (opt = {}), setOptions(opt);
        var img_css = {
                border: "none",
                visibility: "visible",
                margin: 0,
                padding: 0,
                position: "absolute",
                top: 0,
                left: 0
            },
            $origimg = $(obj),
            img_mode = !0;
        if ("IMG" == obj.tagName) {
            if (0 != $origimg[0].width && 0 != $origimg[0].height) $origimg.width($origimg[0].width), $origimg.height($origimg[0].height);
            else {
                var tempImage = new Image;
                tempImage.src = $origimg[0].src, $origimg.width(tempImage.width), $origimg.height(tempImage.height)
            }
            var $img = $origimg.clone().removeAttr("id").css(img_css).show();
            $img.width($origimg.width()), $img.height($origimg.height()), $origimg.after($img).hide()
        } else $img = $origimg.css(img_css).show(), img_mode = !1, null === options.shade && (options.shade = !0);
        presize($img, options.boxWidth, options.boxHeight);
        var boundx = $img.width(),
            boundy = $img.height(),
            $div = $("<div />").width(boundx).height(boundy).addClass(cssClass("holder")).css({
                position: "relative",
                backgroundColor: options.bgColor
            }).insertAfter($origimg).append($img);
        options.addClass && $div.addClass(options.addClass);
        var $img2 = $("<div />"),
            $img_holder = $("<div />").width("100%").height("100%").css({
                zIndex: 310,
                position: "absolute",
                overflow: "hidden"
            }),
            $hdl_holder = $("<div />").width("100%").height("100%").css("zIndex", 320),
            $sel = $("<div />").css({
                position: "absolute",
                zIndex: 600
            }).dblclick(function () {
                var c = Coords.getFixed();
                options.onDblClick.call(api, c)
            }).insertBefore($img).append($img_holder, $hdl_holder);
        img_mode && ($img2 = $("<img />").attr("src", $img.attr("src")).css(img_css).width(boundx).height(boundy), $img_holder.append($img2)), ie6mode && $sel.css({
            overflowY: "hidden"
        });
        var xlimit, ylimit, xmin, ymin, xscale, yscale, btndown, animating, shift_down, bound = options.boundary,
            $trk = newTracker().width(boundx + 2 * bound).height(boundy + 2 * bound).css({
                position: "absolute",
                top: px(-bound),
                left: px(-bound),
                zIndex: 290
            }).mousedown(newSelection),
            bgcolor = options.bgColor,
            bgopacity = options.bgOpacity;
        docOffset = getPos($img);
        var Touch = function () {
                function hasTouchSupport() {
                    var i, support = {},
                        events = ["touchstart", "touchmove", "touchend"],
                        el = document.createElement("div");
                    try {
                        for (i = 0; i < events.length; i++) {
                            var eventName = events[i];
                            eventName = "on" + eventName;
                            var isSupported = eventName in el;
                            isSupported || (el.setAttribute(eventName, "return;"), isSupported = "function" == typeof el[eventName]), support[events[i]] = isSupported
                        }
                        return support.touchstart && support.touchend && support.touchmove
                    } catch (err) {
                        return !1
                    }
                }

                function detectSupport() {
                    return options.touchSupport === !0 || options.touchSupport === !1 ? options.touchSupport : hasTouchSupport()
                }
                return {
                    createDragger: function (ord) {
                        return function (e) {
                            return options.disabled ? !1 : "move" !== ord || options.allowMove ? (docOffset = getPos($img), btndown = !0, startDragMode(ord, mouseAbs(Touch.cfilter(e)), !0), e.stopPropagation(), e.preventDefault(), !1) : !1
                        }
                    },
                    newSelection: function (e) {
                        return newSelection(Touch.cfilter(e))
                    },
                    cfilter: function (e) {
                        return e.pageX = e.originalEvent.changedTouches[0].pageX, e.pageY = e.originalEvent.changedTouches[0].pageY, e
                    },
                    isSupported: hasTouchSupport,
                    support: detectSupport()
                }
            }(),
            Coords = function () {
                function setPressed(pos) {
                    pos = rebound(pos), x2 = x1 = pos[0], y2 = y1 = pos[1]
                }

                function setCurrent(pos) {
                    pos = rebound(pos), ox = pos[0] - x2, oy = pos[1] - y2, x2 = pos[0], y2 = pos[1]
                }

                function getOffset() {
                    return [ox, oy]
                }

                function moveOffset(offset) {
                    var ox = offset[0],
                        oy = offset[1];
                    0 > x1 + ox && (ox -= ox + x1), 0 > y1 + oy && (oy -= oy + y1), y2 + oy > boundy && (oy += boundy - (y2 + oy)), x2 + ox > boundx && (ox += boundx - (x2 + ox)), x1 += ox, x2 += ox, y1 += oy, y2 += oy
                }

                function getCorner(ord) {
                    var c = getFixed();
                    switch (ord) {
                    case "ne":
                        return [c.x2, c.y];
                    case "nw":
                        return [c.x, c.y];
                    case "se":
                        return [c.x2, c.y2];
                    case "sw":
                        return [c.x, c.y2]
                    }
                }

                function getFixed() {
                    if (!options.aspectRatio) return getRect();
                    var xx, yy, w, h, aspect = options.aspectRatio,
                        min_x = options.minSize[0] / xscale,
                        max_x = options.maxSize[0] / xscale,
                        max_y = options.maxSize[1] / yscale,
                        rw = x2 - x1,
                        rh = y2 - y1,
                        rwa = Math.abs(rw),
                        rha = Math.abs(rh),
                        real_ratio = rwa / rha;
                    return 0 === max_x && (max_x = 10 * boundx), 0 === max_y && (max_y = 10 * boundy), aspect > real_ratio ? (yy = y2, w = rha * aspect, xx = 0 > rw ? x1 - w : w + x1, 0 > xx ? (xx = 0, h = Math.abs((xx - x1) / aspect), yy = 0 > rh ? y1 - h : h + y1) : xx > boundx && (xx = boundx, h = Math.abs((xx - x1) / aspect), yy = 0 > rh ? y1 - h : h + y1)) : (xx = x2, h = rwa / aspect, yy = 0 > rh ? y1 - h : y1 + h, 0 > yy ? (yy = 0, w = Math.abs((yy - y1) * aspect), xx = 0 > rw ? x1 - w : w + x1) : yy > boundy && (yy = boundy, w = Math.abs(yy - y1) * aspect, xx = 0 > rw ? x1 - w : w + x1)), xx > x1 ? (min_x > xx - x1 ? xx = x1 + min_x : xx - x1 > max_x && (xx = x1 + max_x), yy = yy > y1 ? y1 + (xx - x1) / aspect : y1 - (xx - x1) / aspect) : x1 > xx && (min_x > x1 - xx ? xx = x1 - min_x : x1 - xx > max_x && (xx = x1 - max_x), yy = yy > y1 ? y1 + (x1 - xx) / aspect : y1 - (x1 - xx) / aspect), 0 > xx ? (x1 -= xx, xx = 0) : xx > boundx && (x1 -= xx - boundx, xx = boundx), 0 > yy ? (y1 -= yy, yy = 0) : yy > boundy && (y1 -= yy - boundy, yy = boundy), makeObj(flipCoords(x1, y1, xx, yy))
                }

                function rebound(p) {
                    return p[0] < 0 && (p[0] = 0), p[1] < 0 && (p[1] = 0), p[0] > boundx && (p[0] = boundx), p[1] > boundy && (p[1] = boundy), [Math.round(p[0]), Math.round(p[1])]
                }

                function flipCoords(x1, y1, x2, y2) {
                    var xa = x1,
                        xb = x2,
                        ya = y1,
                        yb = y2;
                    return x1 > x2 && (xa = x2, xb = x1), y1 > y2 && (ya = y2, yb = y1), [xa, ya, xb, yb]
                }

                function getRect() {
                    var delta, xsize = x2 - x1,
                        ysize = y2 - y1;
                    return xlimit && Math.abs(xsize) > xlimit && (x2 = xsize > 0 ? x1 + xlimit : x1 - xlimit), ylimit && Math.abs(ysize) > ylimit && (y2 = ysize > 0 ? y1 + ylimit : y1 - ylimit), ymin / yscale && Math.abs(ysize) < ymin / yscale && (y2 = ysize > 0 ? y1 + ymin / yscale : y1 - ymin / yscale), xmin / xscale && Math.abs(xsize) < xmin / xscale && (x2 = xsize > 0 ? x1 + xmin / xscale : x1 - xmin / xscale), 0 > x1 && (x2 -= x1, x1 -= x1), 0 > y1 && (y2 -= y1, y1 -= y1), 0 > x2 && (x1 -= x2, x2 -= x2), 0 > y2 && (y1 -= y2, y2 -= y2), x2 > boundx && (delta = x2 - boundx, x1 -= delta, x2 -= delta), y2 > boundy && (delta = y2 - boundy, y1 -= delta, y2 -= delta), x1 > boundx && (delta = x1 - boundy, y2 -= delta, y1 -= delta), y1 > boundy && (delta = y1 - boundy, y2 -= delta, y1 -= delta), makeObj(flipCoords(x1, y1, x2, y2))
                }

                function makeObj(a) {
                    return {
                        x: a[0],
                        y: a[1],
                        x2: a[2],
                        y2: a[3],
                        w: a[2] - a[0],
                        h: a[3] - a[1]
                    }
                }
                var ox, oy, x1 = 0,
                    y1 = 0,
                    x2 = 0,
                    y2 = 0;
                return {
                    flipCoords: flipCoords,
                    setPressed: setPressed,
                    setCurrent: setCurrent,
                    getOffset: getOffset,
                    moveOffset: moveOffset,
                    getCorner: getCorner,
                    getFixed: getFixed
                }
            }(),
            Shade = function () {
                function resizeShades(w, h) {
                    shades.left.css({
                        height: px(h)
                    }), shades.right.css({
                        height: px(h)
                    })
                }

                function updateAuto() {
                    return updateShade(Coords.getFixed())
                }

                function updateShade(c) {
                    shades.top.css({
                        left: px(c.x),
                        width: px(c.w),
                        height: px(c.y)
                    }), shades.bottom.css({
                        top: px(c.y2),
                        left: px(c.x),
                        width: px(c.w),
                        height: px(boundy - c.y2)
                    }), shades.right.css({
                        left: px(c.x2),
                        width: px(boundx - c.x2)
                    }), shades.left.css({
                        width: px(c.x)
                    })
                }

                function createShade() {
                    return $("<div />").css({
                        position: "absolute",
                        backgroundColor: options.shadeColor || options.bgColor
                    }).appendTo(holder)
                }

                function enableShade() {
                    enabled || (enabled = !0, holder.insertBefore($img), updateAuto(), Selection.setBgOpacity(1, 0, 1), $img2.hide(), setBgColor(options.shadeColor || options.bgColor, 1), Selection.isAwake() ? setOpacity(options.bgOpacity, 1) : setOpacity(1, 1))
                }

                function setBgColor(color, now) {
                    colorChangeMacro(getShades(), color, now)
                }

                function disableShade() {
                    enabled && (holder.remove(), $img2.show(), enabled = !1, Selection.isAwake() ? Selection.setBgOpacity(options.bgOpacity, 1, 1) : (Selection.setBgOpacity(1, 1, 1), Selection.disableHandles()), colorChangeMacro($div, 0, 1))
                }

                function setOpacity(opacity, now) {
                    enabled && (options.bgFade && !now ? holder.animate({
                        opacity: 1 - opacity
                    }, {
                        queue: !1,
                        duration: options.fadeTime
                    }) : holder.css({
                        opacity: 1 - opacity
                    }))
                }

                function refreshAll() {
                    options.shade ? enableShade() : disableShade(), Selection.isAwake() && setOpacity(options.bgOpacity)
                }

                function getShades() {
                    return holder.children()
                }
                var enabled = !1,
                    holder = $("<div />").css({
                        position: "absolute",
                        zIndex: 240,
                        opacity: 0
                    }),
                    shades = {
                        top: createShade(),
                        left: createShade().height(boundy),
                        right: createShade().height(boundy),
                        bottom: createShade()
                    };
                return {
                    update: updateAuto,
                    updateRaw: updateShade,
                    getShades: getShades,
                    setBgColor: setBgColor,
                    enable: enableShade,
                    disable: disableShade,
                    resize: resizeShades,
                    refresh: refreshAll,
                    opacity: setOpacity
                }
            }(),
            Selection = function () {
                function insertBorder(type) {
                    var jq = $("<div />").css({
                        position: "absolute",
                        opacity: options.borderOpacity
                    }).addClass(cssClass(type));
                    return $img_holder.append(jq), jq
                }

                function dragDiv(ord, zi) {
                    var jq = $("<div />").mousedown(createDragger(ord)).css({
                        cursor: ord + "-resize",
                        position: "absolute",
                        zIndex: zi
                    }).addClass("ord-" + ord);
                    return Touch.support && jq.bind("touchstart.jcrop", Touch.createDragger(ord)), $hdl_holder.append(jq), jq
                }

                function insertHandle(ord) {
                    var hs = options.handleSize,
                        div = dragDiv(ord, hdep++).css({
                            opacity: options.handleOpacity
                        }).addClass(cssClass("handle"));
                    return hs && div.width(hs).height(hs), div
                }

                function insertDragbar(ord) {
                    return dragDiv(ord, hdep++).addClass("jcrop-dragbar")
                }

                function createDragbars(li) {
                    var i;
                    for (i = 0; i < li.length; i++) dragbar[li[i]] = insertDragbar(li[i])
                }

                function createBorders(li) {
                    var cl, i;
                    for (i = 0; i < li.length; i++) {
                        switch (li[i]) {
                        case "n":
                            cl = "hline";
                            break;
                        case "s":
                            cl = "hline bottom";
                            break;
                        case "e":
                            cl = "vline right";
                            break;
                        case "w":
                            cl = "vline"
                        }
                        borders[li[i]] = insertBorder(cl)
                    }
                }

                function createHandles(li) {
                    var i;
                    for (i = 0; i < li.length; i++) handle[li[i]] = insertHandle(li[i])
                }

                function moveto(x, y) {
                    options.shade || $img2.css({
                        top: px(-y),
                        left: px(-x)
                    }), $sel.css({
                        top: px(y),
                        left: px(x)
                    })
                }

                function resize(w, h) {
                    $sel.width(Math.round(w)).height(Math.round(h))
                }

                function refresh() {
                    var c = Coords.getFixed();
                    Coords.setPressed([c.x, c.y]), Coords.setCurrent([c.x2, c.y2]), updateVisible()
                }

                function updateVisible(select) {
                    return awake ? update(select) : void 0
                }

                function update(select) {
                    var c = Coords.getFixed();
                    resize(c.w, c.h), moveto(c.x, c.y), options.shade && Shade.updateRaw(c), awake || show(), select ? options.onSelect.call(api, unscale(c)) : options.onChange.call(api, unscale(c))
                }

                function setBgOpacity(opacity, force, now) {
                    (awake || force) && (options.bgFade && !now ? $img.animate({
                        opacity: opacity
                    }, {
                        queue: !1,
                        duration: options.fadeTime
                    }) : $img.css("opacity", opacity))
                }

                function show() {
                    $sel.show(), options.shade ? Shade.opacity(bgopacity) : setBgOpacity(bgopacity, !0), awake = !0
                }

                function release() {
                    disableHandles(), $sel.hide(), options.shade ? Shade.opacity(1) : setBgOpacity(1), awake = !1, options.onRelease.call(api)
                }

                function showHandles() {
                    seehandles && $hdl_holder.show()
                }

                function enableHandles() {
                    return seehandles = !0, options.allowResize ? ($hdl_holder.show(), !0) : void 0
                }

                function disableHandles() {
                    seehandles = !1, $hdl_holder.hide()
                }

                function animMode(v) {
                    v ? (animating = !0, disableHandles()) : (animating = !1, enableHandles())
                }

                function done() {
                    animMode(!1), refresh()
                }
                var awake, hdep = 370,
                    borders = {},
                    handle = {},
                    dragbar = {},
                    seehandles = !1;
                options.dragEdges && $.isArray(options.createDragbars) && createDragbars(options.createDragbars), $.isArray(options.createHandles) && createHandles(options.createHandles), options.drawBorders && $.isArray(options.createBorders) && createBorders(options.createBorders), $(document).bind("touchstart.jcrop-ios", function (e) {
                    $(e.currentTarget).hasClass("jcrop-tracker") && e.stopPropagation()
                });
                var $track = newTracker().mousedown(createDragger("move")).css({
                    cursor: "move",
                    position: "absolute",
                    zIndex: 360
                });
                return Touch.support && $track.bind("touchstart.jcrop", Touch.createDragger("move")), $img_holder.append($track), disableHandles(), {
                    updateVisible: updateVisible,
                    update: update,
                    release: release,
                    refresh: refresh,
                    isAwake: function () {
                        return awake
                    },
                    setCursor: function (cursor) {
                        $track.css("cursor", cursor)
                    },
                    enableHandles: enableHandles,
                    enableOnly: function () {
                        seehandles = !0
                    },
                    showHandles: showHandles,
                    disableHandles: disableHandles,
                    animMode: animMode,
                    setBgOpacity: setBgOpacity,
                    done: done
                }
            }(),
            Tracker = function () {
                function toFront(touch) {
                    $trk.css({
                        zIndex: 450
                    }), touch ? $(document).bind("touchmove.jcrop", trackTouchMove).bind("touchend.jcrop", trackTouchEnd) : trackDoc && $(document).bind("mousemove.jcrop", trackMove).bind("mouseup.jcrop", trackUp)
                }

                function toBack() {
                    $trk.css({
                        zIndex: 290
                    }), $(document).unbind("touchmove.jcrop"), $(document).unbind("touchend.jcrop"), $(document).unbind("mousemove.jcrop"), $(document).unbind("mouseup.jcrop")
                }

                function trackMove(e) {
                    return onMove(mouseAbs(e)), !1
                }

                function trackUp(e) {
                    return e.preventDefault(), e.stopPropagation(), btndown && (btndown = !1, onDone(mouseAbs(e)), Selection.isAwake() && options.onSelect.call(api, unscale(Coords.getFixed())), toBack(), onMove = function () {}, onDone = function () {}), !1
                }

                function activateHandlers(move, done, touch) {
                    return btndown = !0, onMove = move, onDone = done, toFront(touch), !1
                }

                function trackTouchMove(e) {
                    return onMove(mouseAbs(Touch.cfilter(e))), !1
                }

                function trackTouchEnd(e) {
                    return trackUp(Touch.cfilter(e))
                }

                function setCursor(t) {
                    $trk.css("cursor", t)
                }
                var onMove = function () {},
                    onDone = function () {},
                    trackDoc = options.trackDocument;
                return trackDoc || $trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp), $img.before($trk), {
                    activateHandlers: activateHandlers,
                    setCursor: setCursor
                }
            }(),
            KeyManager = function () {
                function watchKeys() {
                    options.keySupport && ($keymgr.show(), $keymgr.focus())
                }

                function onBlur() {
                    $keymgr.hide()
                }

                function doNudge(e, x, y) {
                    options.allowMove && (Coords.moveOffset([x, y]), Selection.updateVisible(!0)), e.preventDefault(), e.stopPropagation()
                }

                function parseKey(e) {
                    if (e.ctrlKey || e.metaKey) return !0;
                    shift_down = e.shiftKey ? !0 : !1;
                    var nudge = shift_down ? 10 : 1;
                    switch (e.keyCode) {
                    case 37:
                        doNudge(e, -nudge, 0);
                        break;
                    case 39:
                        doNudge(e, nudge, 0);
                        break;
                    case 38:
                        doNudge(e, 0, -nudge);
                        break;
                    case 40:
                        doNudge(e, 0, nudge);
                        break;
                    case 27:
                        options.allowSelect && Selection.release();
                        break;
                    case 9:
                        return !0
                    }
                    return !1
                }
                var $keymgr = $('<input type="radio" />').css({
                        position: "fixed",
                        left: "-120px",
                        width: "12px"
                    }).addClass("jcrop-keymgr"),
                    $keywrap = $("<div />").css({
                        position: "absolute",
                        overflow: "hidden"
                    }).append($keymgr);
                return options.keySupport && ($keymgr.keydown(parseKey).blur(onBlur), ie6mode || !options.fixedSupport ? ($keymgr.css({
                    position: "absolute",
                    left: "-20px"
                }), $keywrap.append($keymgr).insertBefore($img)) : $keymgr.insertBefore($img)), {
                    watchKeys: watchKeys
                }
            }();
        Touch.support && $trk.bind("touchstart.jcrop", Touch.newSelection), $hdl_holder.hide(), interfaceUpdate(!0);
        var api = {
            setImage: setImage,
            animateTo: animateTo,
            setSelect: setSelect,
            setOptions: setOptionsNew,
            tellSelect: tellSelect,
            tellScaled: tellScaled,
            setClass: setClass,
            disable: disableCrop,
            enable: enableCrop,
            cancel: cancelCrop,
            release: Selection.release,
            destroy: destroy,
            focus: KeyManager.watchKeys,
            getBounds: function () {
                return [boundx * xscale, boundy * yscale]
            },
            getWidgetSize: function () {
                return [boundx, boundy]
            },
            getScaleFactor: function () {
                return [xscale, yscale]
            },
            getOptions: function () {
                return options
            },
            ui: {
                holder: $div,
                selection: $sel
            }
        };
        return is_msie && $div.bind("selectstart", function () {
            return !1
        }), $origimg.data("Jcrop", api), api
    }, $.fn.Jcrop = function (options, callback) {
        var api;
        return this.each(function () {
            if ($(this).data("Jcrop")) {
                if ("api" === options) return $(this).data("Jcrop");
                $(this).data("Jcrop").setOptions(options)
            } else "IMG" == this.tagName ? $.Jcrop.Loader(this, function () {
                $(this).css({
                    display: "block",
                    visibility: "hidden"
                }), api = $.Jcrop(this, options), $.isFunction(callback) && callback.call(api)
            }) : ($(this).css({
                display: "block",
                visibility: "hidden"
            }), api = $.Jcrop(this, options), $.isFunction(callback) && callback.call(api))
        }), this
    }, $.Jcrop.Loader = function (imgobj, success, error) {
        function completeCheck() {
            img.complete ? ($img.unbind(".jcloader"), $.isFunction(success) && success.call(img)) : window.setTimeout(completeCheck, 50)
        }
        var $img = $(imgobj),
            img = $img[0];
        $img.bind("load.jcloader", completeCheck).bind("error.jcloader", function () {
            $img.unbind(".jcloader"), $.isFunction(error) && error.call(img)
        }), img.complete && $.isFunction(success) && ($img.unbind(".jcloader"), success.call(img))
    }, $.Jcrop.defaults = {
        allowSelect: !0,
        allowMove: !0,
        allowResize: !0,
        trackDocument: !0,
        baseClass: "jcrop",
        addClass: null,
        bgColor: "black",
        bgOpacity: .6,
        bgFade: !1,
        borderOpacity: .4,
        handleOpacity: .5,
        handleSize: null,
        aspectRatio: 0,
        keySupport: !0,
        createHandles: ["n", "s", "e", "w", "nw", "ne", "se", "sw"],
        createDragbars: ["n", "s", "e", "w"],
        createBorders: ["n", "s", "e", "w"],
        drawBorders: !0,
        dragEdges: !0,
        fixedSupport: !0,
        touchSupport: null,
        shade: null,
        boxWidth: 0,
        boxHeight: 0,
        boundary: 2,
        fadeTime: 400,
        animationDelay: 20,
        swingSpeed: 3,
        minSelect: [0, 0],
        maxSize: [0, 0],
        minSize: [0, 0],
        onChange: function () {},
        onSelect: function () {},
        onDblClick: function () {},
        onRelease: function () {}
    }
}(jQuery),
function ($) {
    "use strict";

    function doAjaxSubmit(e) {
        var options = e.data;
        e.isDefaultPrevented() || (e.preventDefault(), $(this).ajaxSubmit(options))
    }

    function captureSubmittingElement(e) {
        var target = e.target,
            $el = $(target);
        if (!$el.is("[type=submit],[type=image]")) {
            var t = $el.closest("[type=submit]");
            if (0 === t.length) return;
            target = t[0]
        }
        var form = this;
        if (form.clk = target, "image" == target.type)
            if (void 0 !== e.offsetX) form.clk_x = e.offsetX, form.clk_y = e.offsetY;
            else if ("function" == typeof $.fn.offset) {
            var offset = $el.offset();
            form.clk_x = e.pageX - offset.left, form.clk_y = e.pageY - offset.top
        } else form.clk_x = e.pageX - target.offsetLeft, form.clk_y = e.pageY - target.offsetTop;
        setTimeout(function () {
            form.clk = form.clk_x = form.clk_y = null
        }, 100)
    }

    function log() {
        if ($.fn.ajaxSubmit.debug) {
            var msg = "[jquery.form] " + Array.prototype.join.call(arguments, "");
            window.console && window.console.log ? window.console.log(msg) : window.opera && window.opera.postError && window.opera.postError(msg)
        }
    }
    var feature = {};
    feature.fileapi = void 0 !== $("<input type='file'/>").get(0).files, feature.formdata = void 0 !== window.FormData, $.fn.ajaxSubmit = function (options) {
        function deepSerialize(extraData) {
            var i, part, serialized = $.param(extraData).split("&"),
                len = serialized.length,
                result = [];
            for (i = 0; len > i; i++) serialized[i] = serialized[i].replace(/\+/g, " "), part = serialized[i].split("="), result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);
            return result
        }

        function fileUploadXhr(a) {
            for (var formdata = new FormData, i = 0; i < a.length; i++) formdata.append(a[i].name, a[i].value);
            if (options.extraData) {
                var serializedData = deepSerialize(options.extraData);
                for (i = 0; i < serializedData.length; i++) serializedData[i] && formdata.append(serializedData[i][0], serializedData[i][1])
            }
            options.data = null;
            var s = $.extend(!0, {}, $.ajaxSettings, options, {
                contentType: !1,
                processData: !1,
                cache: !1,
                type: method || "POST"
            });
            options.uploadProgress && (s.xhr = function () {
                var xhr = jQuery.ajaxSettings.xhr();
                return xhr.upload && xhr.upload.addEventListener("progress", function (event) {
                    var percent = 0,
                        position = event.loaded || event.position,
                        total = event.total;
                    event.lengthComputable && (percent = Math.ceil(100 * (position / total))), options.uploadProgress(event, position, total, percent)
                }, !1), xhr
            }), s.data = null;
            var beforeSend = s.beforeSend;
            return s.beforeSend = function (xhr, o) {
                o.data = formdata, beforeSend && beforeSend.call(this, xhr, o)
            }, $.ajax(s)
        }

        function fileUploadIframe(a) {
            function getDoc(frame) {
                var doc = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument ? frame.contentDocument : frame.document;
                return doc
            }

            function doSubmit() {
                function checkState() {
                    try {
                        var state = getDoc(io).readyState;
                        log("state = " + state), state && "uninitialized" == state.toLowerCase() && setTimeout(checkState, 50)
                    } catch (e) {
                        log("Server abort: ", e, " (", e.name, ")"), cb(SERVER_ABORT), timeoutHandle && clearTimeout(timeoutHandle), timeoutHandle = void 0
                    }
                }
                var t = $form.attr("target"),
                    a = $form.attr("action");
                form.setAttribute("target", id), method || form.setAttribute("method", "POST"), a != s.url && form.setAttribute("action", s.url), s.skipEncodingOverride || method && !/post/i.test(method) || $form.attr({
                    encoding: "multipart/form-data",
                    enctype: "multipart/form-data"
                }), s.timeout && (timeoutHandle = setTimeout(function () {
                    timedOut = !0, cb(CLIENT_TIMEOUT_ABORT)
                }, s.timeout));
                var extraInputs = [];
                try {
                    if (s.extraData)
                        for (var n in s.extraData) s.extraData.hasOwnProperty(n) && ($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty("name") && s.extraData[n].hasOwnProperty("value") ? extraInputs.push($('<input type="hidden" name="' + s.extraData[n].name + '">').val(s.extraData[n].value).appendTo(form)[0]) : extraInputs.push($('<input type="hidden" name="' + n + '">').val(s.extraData[n]).appendTo(form)[0]));
                    s.iframeTarget || ($io.appendTo("body"), io.attachEvent ? io.attachEvent("onload", cb) : io.addEventListener("load", cb, !1)), setTimeout(checkState, 15);
                    var submitFn = document.createElement("form").submit;
                    submitFn.apply(form)
                } finally {
                    form.setAttribute("action", a), t ? form.setAttribute("target", t) : $form.removeAttr("target"), $(extraInputs).remove()
                }
            }

            function cb(e) {
                if (!xhr.aborted && !callbackProcessed) {
                    try {
                        doc = getDoc(io)
                    } catch (ex) {
                        log("cannot access response document: ", ex), e = SERVER_ABORT
                    }
                    if (e === CLIENT_TIMEOUT_ABORT && xhr) return xhr.abort("timeout"), deferred.reject(xhr, "timeout"), void 0;
                    if (e == SERVER_ABORT && xhr) return xhr.abort("server abort"), deferred.reject(xhr, "error", "server abort"), void 0;
                    if (doc && doc.location.href != s.iframeSrc || timedOut) {
                        io.detachEvent ? io.detachEvent("onload", cb) : io.removeEventListener("load", cb, !1);
                        var errMsg, status = "success";
                        try {
                            if (timedOut) throw "timeout";
                            var isXml = "xml" == s.dataType || doc.XMLDocument || $.isXMLDoc(doc);
                            if (log("isXml=" + isXml), !isXml && window.opera && (null === doc.body || !doc.body.innerHTML) && --domCheckCount) return log("requeing onLoad callback, DOM not available"), setTimeout(cb, 250), void 0;
                            var docRoot = doc.body ? doc.body : doc.documentElement;
                            xhr.responseText = docRoot ? docRoot.innerHTML : null, xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc, isXml && (s.dataType = "xml"), xhr.getResponseHeader = function (header) {
                                var headers = {
                                    "content-type": s.dataType
                                };
                                return headers[header]
                            }, docRoot && (xhr.status = Number(docRoot.getAttribute("status")) || xhr.status, xhr.statusText = docRoot.getAttribute("statusText") || xhr.statusText);
                            var dt = (s.dataType || "").toLowerCase(),
                                scr = /(json|script|text)/.test(dt);
                            if (scr || s.textarea) {
                                var ta = doc.getElementsByTagName("textarea")[0];
                                if (ta) xhr.responseText = ta.value, xhr.status = Number(ta.getAttribute("status")) || xhr.status, xhr.statusText = ta.getAttribute("statusText") || xhr.statusText;
                                else if (scr) {
                                    var pre = doc.getElementsByTagName("pre")[0],
                                        b = doc.getElementsByTagName("body")[0];
                                    pre ? xhr.responseText = pre.textContent ? pre.textContent : pre.innerText : b && (xhr.responseText = b.textContent ? b.textContent : b.innerText)
                                }
                            } else "xml" == dt && !xhr.responseXML && xhr.responseText && (xhr.responseXML = toXml(xhr.responseText));
                            try {
                                data = httpData(xhr, dt, s)
                            } catch (e) {
                                status = "parsererror", xhr.error = errMsg = e || status
                            }
                        } catch (e) {
                            log("error caught: ", e), status = "error", xhr.error = errMsg = e || status
                        }
                        xhr.aborted && (log("upload aborted"), status = null), xhr.status && (status = xhr.status >= 200 && xhr.status < 300 || 304 === xhr.status ? "success" : "error"), "success" === status ? (s.success && s.success.call(s.context, data, "success", xhr), deferred.resolve(xhr.responseText, "success", xhr), g && $.event.trigger("ajaxSuccess", [xhr, s])) : status && (void 0 === errMsg && (errMsg = xhr.statusText), s.error && s.error.call(s.context, xhr, status, errMsg), deferred.reject(xhr, "error", errMsg), g && $.event.trigger("ajaxError", [xhr, s, errMsg])), g && $.event.trigger("ajaxComplete", [xhr, s]), g && !--$.active && $.event.trigger("ajaxStop"), s.complete && s.complete.call(s.context, xhr, status), callbackProcessed = !0, s.timeout && clearTimeout(timeoutHandle), setTimeout(function () {
                            s.iframeTarget || $io.remove(), xhr.responseXML = null
                        }, 100)
                    }
                }
            }
            var el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle, form = $form[0],
                useProp = !!$.fn.prop,
                deferred = $.Deferred();
            if (a)
                for (i = 0; i < elements.length; i++) el = $(elements[i]), useProp ? el.prop("disabled", !1) : el.removeAttr("disabled");
            if (s = $.extend(!0, {}, $.ajaxSettings, options), s.context = s.context || s, id = "jqFormIO" + (new Date).getTime(), s.iframeTarget ? ($io = $(s.iframeTarget), n = $io.attr("name"), n ? id = n : $io.attr("name", id)) : ($io = $('<iframe name="' + id + '" src="' + s.iframeSrc + '" />'), $io.css({
                position: "absolute",
                top: "-1000px",
                left: "-1000px"
            })), io = $io[0], xhr = {
                aborted: 0,
                responseText: null,
                responseXML: null,
                status: 0,
                statusText: "n/a",
                getAllResponseHeaders: function () {},
                getResponseHeader: function () {},
                setRequestHeader: function () {},
                abort: function (status) {
                    var e = "timeout" === status ? "timeout" : "aborted";
                    log("aborting upload... " + e), this.aborted = 1;
                    try {
                        io.contentWindow.document.execCommand && io.contentWindow.document.execCommand("Stop")
                    } catch (ignore) {}
                    $io.attr("src", s.iframeSrc), xhr.error = e, s.error && s.error.call(s.context, xhr, e, status), g && $.event.trigger("ajaxError", [xhr, s, e]), s.complete && s.complete.call(s.context, xhr, e)
                }
            }, g = s.global, g && 0 === $.active++ && $.event.trigger("ajaxStart"), g && $.event.trigger("ajaxSend", [xhr, s]), s.beforeSend && s.beforeSend.call(s.context, xhr, s) === !1) return s.global && $.active--, deferred.reject(), deferred;
            if (xhr.aborted) return deferred.reject(), deferred;
            sub = form.clk, sub && (n = sub.name, n && !sub.disabled && (s.extraData = s.extraData || {}, s.extraData[n] = sub.value, "image" == sub.type && (s.extraData[n + ".x"] = form.clk_x, s.extraData[n + ".y"] = form.clk_y)));
            var CLIENT_TIMEOUT_ABORT = 1,
                SERVER_ABORT = 2,
                csrf_token = $("meta[name=csrf-token]").attr("content"),
                csrf_param = $("meta[name=csrf-param]").attr("content");
            csrf_param && csrf_token && (s.extraData = s.extraData || {}, s.extraData[csrf_param] = csrf_token), s.forceSync ? doSubmit() : setTimeout(doSubmit, 10);
            var data, doc, callbackProcessed, domCheckCount = 50,
                toXml = $.parseXML || function (s, doc) {
                    return window.ActiveXObject ? (doc = new ActiveXObject("Microsoft.XMLDOM"), doc.async = "false", doc.loadXML(s)) : doc = (new DOMParser).parseFromString(s, "text/xml"), doc && doc.documentElement && "parsererror" != doc.documentElement.nodeName ? doc : null
                },
                parseJSON = $.parseJSON || function (s) {
                    return window.eval("(" + s + ")")
                },
                httpData = function (xhr, type, s) {
                    var ct = xhr.getResponseHeader("content-type") || "",
                        xml = "xml" === type || !type && ct.indexOf("xml") >= 0,
                        data = xml ? xhr.responseXML : xhr.responseText;
                    return xml && "parsererror" === data.documentElement.nodeName && $.error && $.error("parsererror"), s && s.dataFilter && (data = s.dataFilter(data, type)), "string" == typeof data && ("json" === type || !type && ct.indexOf("json") >= 0 ? data = parseJSON(data) : ("script" === type || !type && ct.indexOf("javascript") >= 0) && $.globalEval(data)), data
                };
            return deferred
        }
        if (!this.length) return log("ajaxSubmit: skipping submit process - no element selected"), this;
        var method, action, url, $form = this;
        "function" == typeof options && (options = {
            success: options
        }), method = this.attr("method"), action = this.attr("action"), url = "string" == typeof action ? $.trim(action) : "", url = url || window.location.href || "", url && (url = (url.match(/^([^#]+)/) || [])[1]), options = $.extend(!0, {
            url: url,
            success: $.ajaxSettings.success,
            type: method || "GET",
            iframeSrc: /^https/i.test(window.location.href || "") ? "javascript:false" : "about:blank"
        }, options);
        var veto = {};
        if (this.trigger("form-pre-serialize", [this, options, veto]), veto.veto) return log("ajaxSubmit: submit vetoed via form-pre-serialize trigger"), this;
        if (options.beforeSerialize && options.beforeSerialize(this, options) === !1) return log("ajaxSubmit: submit aborted via beforeSerialize callback"), this;
        var traditional = options.traditional;
        void 0 === traditional && (traditional = $.ajaxSettings.traditional);
        var qx, elements = [],
            a = this.formToArray(options.semantic, elements);
        if (options.data && (options.extraData = options.data, qx = $.param(options.data, traditional)), options.beforeSubmit && options.beforeSubmit(a, this, options) === !1) return log("ajaxSubmit: submit aborted via beforeSubmit callback"), this;
        if (this.trigger("form-submit-validate", [a, this, options, veto]), veto.veto) return log("ajaxSubmit: submit vetoed via form-submit-validate trigger"), this;
        var q = $.param(a, traditional);
        qx && (q = q ? q + "&" + qx : qx), "GET" == options.type.toUpperCase() ? (options.url += (options.url.indexOf("?") >= 0 ? "&" : "?") + q, options.data = null) : options.data = q;
        var callbacks = [];
        if (options.resetForm && callbacks.push(function () {
            $form.resetForm()
        }), options.clearForm && callbacks.push(function () {
            $form.clearForm(options.includeHidden)
        }), !options.dataType && options.target) {
            var oldSuccess = options.success || function () {};
            callbacks.push(function (data) {
                var fn = options.replaceTarget ? "replaceWith" : "html";
                $(options.target)[fn](data).each(oldSuccess, arguments)
            })
        } else options.success && callbacks.push(options.success);
        options.success = function (data, status, xhr) {
            for (var context = options.context || this, i = 0, max = callbacks.length; max > i; i++) callbacks[i].apply(context, [data, status, xhr || $form, $form])
        };
        var fileInputs = $('input[type=file]:enabled[value!=""]', this),
            hasFileInputs = fileInputs.length > 0,
            mp = "multipart/form-data",
            multipart = $form.attr("enctype") == mp || $form.attr("encoding") == mp,
            fileAPI = feature.fileapi && feature.formdata;
        log("fileAPI :" + fileAPI);
        var jqxhr, shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
        options.iframe !== !1 && (options.iframe || shouldUseFrame) ? options.closeKeepAlive ? $.get(options.closeKeepAlive, function () {
            jqxhr = fileUploadIframe(a)
        }) : jqxhr = fileUploadIframe(a) : jqxhr = (hasFileInputs || multipart) && fileAPI ? fileUploadXhr(a) : $.ajax(options), $form.removeData("jqxhr").data("jqxhr", jqxhr);
        for (var k = 0; k < elements.length; k++) elements[k] = null;
        return this.trigger("form-submit-notify", [this, options]), this
    }, $.fn.ajaxForm = function (options) {
        if (options = options || {}, options.delegation = options.delegation && $.isFunction($.fn.on), !options.delegation && 0 === this.length) {
            var o = {
                s: this.selector,
                c: this.context
            };
            return !$.isReady && o.s ? (log("DOM not ready, queuing ajaxForm"), $(function () {
                $(o.s, o.c).ajaxForm(options)
            }), this) : (log("terminating; zero elements found by selector" + ($.isReady ? "" : " (DOM not ready)")), this)
        }
        return options.delegation ? ($(document).off("submit.form-plugin", this.selector, doAjaxSubmit).off("click.form-plugin", this.selector, captureSubmittingElement).on("submit.form-plugin", this.selector, options, doAjaxSubmit).on("click.form-plugin", this.selector, options, captureSubmittingElement), this) : this.ajaxFormUnbind().bind("submit.form-plugin", options, doAjaxSubmit).bind("click.form-plugin", options, captureSubmittingElement)
    }, $.fn.ajaxFormUnbind = function () {
        return this.unbind("submit.form-plugin click.form-plugin")
    }, $.fn.formToArray = function (semantic, elements) {
        var a = [];
        if (0 === this.length) return a;
        var form = this[0],
            els = semantic ? form.getElementsByTagName("*") : form.elements;
        if (!els) return a;
        var i, j, n, v, el, max, jmax;
        for (i = 0, max = els.length; max > i; i++)
            if (el = els[i], n = el.name)
                if (semantic && form.clk && "image" == el.type) el.disabled || form.clk != el || (a.push({
                    name: n,
                    value: $(el).val(),
                    type: el.type
                }), a.push({
                    name: n + ".x",
                    value: form.clk_x
                }, {
                    name: n + ".y",
                    value: form.clk_y
                }));
                else if (v = $.fieldValue(el, !0), v && v.constructor == Array)
            for (elements && elements.push(el), j = 0, jmax = v.length; jmax > j; j++) a.push({
                name: n,
                value: v[j]
            });
        else if (feature.fileapi && "file" == el.type && !el.disabled) {
            elements && elements.push(el);
            var files = el.files;
            if (files.length)
                for (j = 0; j < files.length; j++) a.push({
                    name: n,
                    value: files[j],
                    type: el.type
                });
            else a.push({
                name: n,
                value: "",
                type: el.type
            })
        } else null !== v && "undefined" != typeof v && (elements && elements.push(el), a.push({
            name: n,
            value: v,
            type: el.type,
            required: el.required
        })); if (!semantic && form.clk) {
            var $input = $(form.clk),
                input = $input[0];
            n = input.name, n && !input.disabled && "image" == input.type && (a.push({
                name: n,
                value: $input.val()
            }), a.push({
                name: n + ".x",
                value: form.clk_x
            }, {
                name: n + ".y",
                value: form.clk_y
            }))
        }
        return a
    }, $.fn.formSerialize = function (semantic) {
        return $.param(this.formToArray(semantic))
    }, $.fn.fieldSerialize = function (successful) {
        var a = [];
        return this.each(function () {
            var n = this.name;
            if (n) {
                var v = $.fieldValue(this, successful);
                if (v && v.constructor == Array)
                    for (var i = 0, max = v.length; max > i; i++) a.push({
                        name: n,
                        value: v[i]
                    });
                else null !== v && "undefined" != typeof v && a.push({
                    name: this.name,
                    value: v
                })
            }
        }), $.param(a)
    }, $.fn.fieldValue = function (successful) {
        for (var val = [], i = 0, max = this.length; max > i; i++) {
            var el = this[i],
                v = $.fieldValue(el, successful);
            null === v || "undefined" == typeof v || v.constructor == Array && !v.length || (v.constructor == Array ? $.merge(val, v) : val.push(v))
        }
        return val
    }, $.fieldValue = function (el, successful) {
        var n = el.name,
            t = el.type,
            tag = el.tagName.toLowerCase();
        if (void 0 === successful && (successful = !0), successful && (!n || el.disabled || "reset" == t || "button" == t || ("checkbox" == t || "radio" == t) && !el.checked || ("submit" == t || "image" == t) && el.form && el.form.clk != el || "select" == tag && -1 == el.selectedIndex)) return null;
        if ("select" == tag) {
            var index = el.selectedIndex;
            if (0 > index) return null;
            for (var a = [], ops = el.options, one = "select-one" == t, max = one ? index + 1 : ops.length, i = one ? index : 0; max > i; i++) {
                var op = ops[i];
                if (op.selected) {
                    var v = op.value;
                    if (v || (v = op.attributes && op.attributes.value && !op.attributes.value.specified ? op.text : op.value), one) return v;
                    a.push(v)
                }
            }
            return a
        }
        return $(el).val()
    }, $.fn.clearForm = function (includeHidden) {
        return this.each(function () {
            $("input,select,textarea", this).clearFields(includeHidden)
        })
    }, $.fn.clearFields = $.fn.clearInputs = function (includeHidden) {
        var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i;
        return this.each(function () {
            var t = this.type,
                tag = this.tagName.toLowerCase();
            re.test(t) || "textarea" == tag ? this.value = "" : "checkbox" == t || "radio" == t ? this.checked = !1 : "select" == tag ? this.selectedIndex = -1 : "file" == t ? /MSIE/.test(navigator.userAgent) ? $(this).replaceWith($(this).clone()) : $(this).val("") : includeHidden && (includeHidden === !0 && /hidden/.test(t) || "string" == typeof includeHidden && $(this).is(includeHidden)) && (this.value = "")
        })
    }, $.fn.resetForm = function () {
        return this.each(function () {
            ("function" == typeof this.reset || "object" == typeof this.reset && !this.reset.nodeType) && this.reset()
        })
    }, $.fn.enable = function (b) {
        return void 0 === b && (b = !0), this.each(function () {
            this.disabled = !b
        })
    }, $.fn.selected = function (select) {
        return void 0 === select && (select = !0), this.each(function () {
            var t = this.type;
            if ("checkbox" == t || "radio" == t) this.checked = select;
            else if ("option" == this.tagName.toLowerCase()) {
                var $sel = $(this).parent("select");
                select && $sel[0] && "select-one" == $sel[0].type && $sel.find("option").selected(!1), this.selected = select
            }
        })
    }, $.fn.ajaxSubmit.debug = !1
}(jQuery),
function (factory) {
    "use strict";
    "function" == typeof define && define.amd ? define(["jquery"], factory) : factory(window.jQuery)
}(function ($) {
    "use strict";
    var counter = 0;
    $.ajaxTransport("iframe", function (options) {
        if (options.async) {
            var form, iframe, addParamChar;
            return {
                send: function (_, completeCallback) {
                    form = $('<form style="display:none;"></form>'), form.attr("accept-charset", options.formAcceptCharset), addParamChar = /\?/.test(options.url) ? "&" : "?", "DELETE" === options.type ? (options.url = options.url + addParamChar + "_method=DELETE", options.type = "POST") : "PUT" === options.type ? (options.url = options.url + addParamChar + "_method=PUT", options.type = "POST") : "PATCH" === options.type && (options.url = options.url + addParamChar + "_method=PATCH", options.type = "POST"), iframe = $('<iframe src="javascript:false;" name="iframe-transport-' + (counter += 1) + '"></iframe>').bind("load", function () {
                        var fileInputClones, paramNames = $.isArray(options.paramName) ? options.paramName : [options.paramName];
                        iframe.unbind("load").bind("load", function () {
                            var response;
                            try {
                                if (response = iframe.contents(), !response.length || !response[0].firstChild) throw new Error
                            } catch (e) {
                                response = void 0
                            }
                            completeCallback(200, "success", {
                                iframe: response
                            }), $('<iframe src="javascript:false;"></iframe>').appendTo(form), form.remove()
                        }), form.prop("target", iframe.prop("name")).prop("action", options.url).prop("method", options.type), options.formData && $.each(options.formData, function (index, field) {
                            $('<input type="hidden"/>').prop("name", field.name).val(field.value).appendTo(form)
                        }), options.fileInput && options.fileInput.length && "POST" === options.type && (fileInputClones = options.fileInput.clone(), options.fileInput.after(function (index) {
                            return fileInputClones[index]
                        }), options.paramName && options.fileInput.each(function (index) {
                            $(this).prop("name", paramNames[index] || options.paramName)
                        }), form.append(options.fileInput).prop("enctype", "multipart/form-data").prop("encoding", "multipart/form-data")), form.submit(), fileInputClones && fileInputClones.length && options.fileInput.each(function (index, input) {
                            var clone = $(fileInputClones[index]);
                            $(input).prop("name", clone.prop("name")), clone.replaceWith(input)
                        })
                    }), form.append(iframe).appendTo(document.body)
                },
                abort: function () {
                    iframe && iframe.unbind("load").prop("src", "javascript".concat(":false;")), form && form.remove()
                }
            }
        }
    }), $.ajaxSetup({
        converters: {
            "iframe text": function (iframe) {
                return iframe && $(iframe[0].body).text()
            },
            "iframe json": function (iframe) {
                return iframe && $.parseJSON($(iframe[0].body).text())
            },
            "iframe html": function (iframe) {
                return iframe && $(iframe[0].body).html()
            },
            "iframe script": function (iframe) {
                return iframe && $.globalEval($(iframe[0].body).text())
            }
        }
    })
}),
function (factory) {
    "use strict";
    "function" == typeof define && define.amd ? define(["jquery", "jquery.ui.widget"], factory) : factory(window.jQuery)
}(function ($) {
    "use strict";
    $.support.xhrFileUpload = !(!window.XMLHttpRequestUpload || !window.FileReader), $.support.xhrFormDataFileUpload = !!window.FormData, $.widget("blueimp.fileupload", {
        options: {
            dropZone: $(document),
            pasteZone: $(document),
            fileInput: void 0,
            replaceFileInput: !0,
            paramName: void 0,
            singleFileUploads: !0,
            limitMultiFileUploads: void 0,
            sequentialUploads: !1,
            limitConcurrentUploads: void 0,
            forceIframeTransport: !1,
            redirect: void 0,
            redirectParamName: void 0,
            postMessage: void 0,
            multipart: !0,
            maxChunkSize: void 0,
            uploadedBytes: void 0,
            recalculateProgress: !0,
            progressInterval: 100,
            bitrateInterval: 500,
            autoUpload: !0,
            messages: {
                uploadedBytes: "Uploaded bytes exceed file size"
            },
            i18n: function (message, context) {
                return message = this.messages[message] || message.toString(), context && $.each(context, function (key, value) {
                    message = message.replace("{" + key + "}", value)
                }), message
            },
            formData: function (form) {
                return form.serializeArray()
            },
            add: function (e, data) {
                (data.autoUpload || data.autoUpload !== !1 && $(this).fileupload("option", "autoUpload")) && data.process().done(function () {
                    data.submit()
                })
            },
            processData: !1,
            contentType: !1,
            cache: !1
        },
        _specialOptions: ["fileInput", "dropZone", "pasteZone", "multipart", "forceIframeTransport"],
        _BitrateTimer: function () {
            this.timestamp = Date.now ? Date.now() : (new Date).getTime(), this.loaded = 0, this.bitrate = 0, this.getBitrate = function (now, loaded, interval) {
                var timeDiff = now - this.timestamp;
                return (!this.bitrate || !interval || timeDiff > interval) && (this.bitrate = 8 * (loaded - this.loaded) * (1e3 / timeDiff), this.loaded = loaded, this.timestamp = now), this.bitrate
            }
        },
        _isXHRUpload: function (options) {
            return !options.forceIframeTransport && (!options.multipart && $.support.xhrFileUpload || $.support.xhrFormDataFileUpload)
        },
        _getFormData: function (options) {
            var formData;
            return "function" == typeof options.formData ? options.formData(options.form) : $.isArray(options.formData) ? options.formData : "object" === $.type(options.formData) ? (formData = [], $.each(options.formData, function (name, value) {
                formData.push({
                    name: name,
                    value: value
                })
            }), formData) : []
        },
        _getTotal: function (files) {
            var total = 0;
            return $.each(files, function (index, file) {
                total += file.size || 1
            }), total
        },
        _initProgressObject: function (obj) {
            var progress = {
                loaded: 0,
                total: 0,
                bitrate: 0
            };
            obj._progress ? $.extend(obj._progress, progress) : obj._progress = progress
        },
        _initResponseObject: function (obj) {
            var prop;
            if (obj._response)
                for (prop in obj._response) obj._response.hasOwnProperty(prop) && delete obj._response[prop];
            else obj._response = {}
        },
        _onProgress: function (e, data) {
            if (e.lengthComputable) {
                var loaded, now = Date.now ? Date.now() : (new Date).getTime();
                if (data._time && data.progressInterval && now - data._time < data.progressInterval && e.loaded !== e.total) return;
                data._time = now, loaded = Math.floor(e.loaded / e.total * (data.chunkSize || data._progress.total)) + (data.uploadedBytes || 0), this._progress.loaded += loaded - data._progress.loaded, this._progress.bitrate = this._bitrateTimer.getBitrate(now, this._progress.loaded, data.bitrateInterval), data._progress.loaded = data.loaded = loaded, data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate(now, loaded, data.bitrateInterval), this._trigger("progress", e, data), this._trigger("progressall", e, this._progress)
            }
        },
        _initProgressListener: function (options) {
            var that = this,
                xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr();
            xhr.upload && ($(xhr.upload).bind("progress", function (e) {
                var oe = e.originalEvent;
                e.lengthComputable = oe.lengthComputable, e.loaded = oe.loaded, e.total = oe.total, that._onProgress(e, options)
            }), options.xhr = function () {
                return xhr
            })
        },
        _isInstanceOf: function (type, obj) {
            return Object.prototype.toString.call(obj) === "[object " + type + "]"
        },
        _initXHRData: function (options) {
            var formData, that = this,
                file = options.files[0],
                multipart = options.multipart || !$.support.xhrFileUpload,
                paramName = options.paramName[0];
            options.headers = options.headers || {}, options.contentRange && (options.headers["Content-Range"] = options.contentRange), multipart ? $.support.xhrFormDataFileUpload && (options.postMessage ? (formData = this._getFormData(options), options.blob ? formData.push({
                name: paramName,
                value: options.blob
            }) : $.each(options.files, function (index, file) {
                formData.push({
                    name: options.paramName[index] || paramName,
                    value: file
                })
            })) : (that._isInstanceOf("FormData", options.formData) ? formData = options.formData : (formData = new FormData, $.each(this._getFormData(options), function (index, field) {
                formData.append(field.name, field.value)
            })), options.blob ? (options.headers["Content-Disposition"] = 'attachment; filename="' + encodeURI(file.name) + '"', formData.append(paramName, options.blob, file.name)) : $.each(options.files, function (index, file) {
                (that._isInstanceOf("File", file) || that._isInstanceOf("Blob", file)) && formData.append(options.paramName[index] || paramName, file, file.name)
            })), options.data = formData) : (options.headers["Content-Disposition"] = 'attachment; filename="' + encodeURI(file.name) + '"', options.contentType = file.type, options.data = options.blob || file), options.blob = null
        },
        _initIframeSettings: function (options) {
            options.dataType = "iframe " + (options.dataType || ""), options.formData = this._getFormData(options), options.redirect && $("<a></a>").prop("href", options.url).prop("host") !== location.host && options.formData.push({
                name: options.redirectParamName || "redirect",
                value: options.redirect
            })
        },
        _initDataSettings: function (options) {
            this._isXHRUpload(options) ? (this._chunkedUpload(options, !0) || (options.data || this._initXHRData(options), this._initProgressListener(options)), options.postMessage && (options.dataType = "postmessage " + (options.dataType || ""))) : this._initIframeSettings(options)
        },
        _getParamName: function (options) {
            var fileInput = $(options.fileInput),
                paramName = options.paramName;
            return paramName ? $.isArray(paramName) || (paramName = [paramName]) : (paramName = [], fileInput.each(function () {
                for (var input = $(this), name = input.prop("name") || "files[]", i = (input.prop("files") || [1]).length; i;) paramName.push(name), i -= 1
            }), paramName.length || (paramName = [fileInput.prop("name") || "files[]"])), paramName
        },
        _initFormSettings: function (options) {
            options.form && options.form.length || (options.form = $(options.fileInput.prop("form")), options.form.length || (options.form = $(this.options.fileInput.prop("form")))), options.paramName = this._getParamName(options), options.url || (options.url = options.form.prop("action") || location.href), options.type = (options.type || options.form.prop("method") || "").toUpperCase(), "POST" !== options.type && "PUT" !== options.type && "PATCH" !== options.type && (options.type = "POST"), options.formAcceptCharset || (options.formAcceptCharset = options.form.attr("accept-charset"))
        },
        _getAJAXSettings: function (data) {
            var options = $.extend({}, this.options, data);
            return this._initFormSettings(options), this._initDataSettings(options), options
        },
        _getDeferredState: function (deferred) {
            return deferred.state ? deferred.state() : deferred.isResolved() ? "resolved" : deferred.isRejected() ? "rejected" : "pending"
        },
        _enhancePromise: function (promise) {
            return promise.success = promise.done, promise.error = promise.fail, promise.complete = promise.always, promise
        },
        _getXHRPromise: function (resolveOrReject, context, args) {
            var dfd = $.Deferred(),
                promise = dfd.promise();
            return context = context || this.options.context || promise, resolveOrReject === !0 ? dfd.resolveWith(context, args) : resolveOrReject === !1 && dfd.rejectWith(context, args), promise.abort = dfd.promise, this._enhancePromise(promise)
        },
        _addConvenienceMethods: function (e, data) {
            var that = this,
                getPromise = function (data) {
                    return $.Deferred().resolveWith(that, [data]).promise()
                };
            data.process = function (resolveFunc, rejectFunc) {
                return (resolveFunc || rejectFunc) && (data._processQueue = this._processQueue = (this._processQueue || getPromise(this)).pipe(resolveFunc, rejectFunc)), this._processQueue || getPromise(this)
            }, data.submit = function () {
                return "pending" !== this.state() && (data.jqXHR = this.jqXHR = that._trigger("submit", e, this) !== !1 && that._onSend(e, this)), this.jqXHR || that._getXHRPromise()
            }, data.abort = function () {
                return this.jqXHR ? this.jqXHR.abort() : that._getXHRPromise()
            }, data.state = function () {
                return this.jqXHR ? that._getDeferredState(this.jqXHR) : this._processQueue ? that._getDeferredState(this._processQueue) : void 0
            }, data.progress = function () {
                return this._progress
            }, data.response = function () {
                return this._response
            }
        },
        _getUploadedBytes: function (jqXHR) {
            var range = jqXHR.getResponseHeader("Range"),
                parts = range && range.split("-"),
                upperBytesPos = parts && parts.length > 1 && parseInt(parts[1], 10);
            return upperBytesPos && upperBytesPos + 1
        },
        _chunkedUpload: function (options, testOnly) {
            var jqXHR, upload, that = this,
                file = options.files[0],
                fs = file.size,
                ub = options.uploadedBytes = options.uploadedBytes || 0,
                mcs = options.maxChunkSize || fs,
                slice = file.slice || file.webkitSlice || file.mozSlice,
                dfd = $.Deferred(),
                promise = dfd.promise();
            return this._isXHRUpload(options) && slice && (ub || fs > mcs) && !options.data ? testOnly ? !0 : ub >= fs ? (file.error = options.i18n("uploadedBytes"), this._getXHRPromise(!1, options.context, [null, "error", file.error])) : (upload = function () {
                var o = $.extend({}, options),
                    currentLoaded = o._progress.loaded;
                o.blob = slice.call(file, ub, ub + mcs, file.type), o.chunkSize = o.blob.size, o.contentRange = "bytes " + ub + "-" + (ub + o.chunkSize - 1) + "/" + fs, that._initXHRData(o), that._initProgressListener(o), jqXHR = (that._trigger("chunksend", null, o) !== !1 && $.ajax(o) || that._getXHRPromise(!1, o.context)).done(function (result, textStatus, jqXHR) {
                    ub = that._getUploadedBytes(jqXHR) || ub + o.chunkSize, o._progress.loaded === currentLoaded && that._onProgress($.Event("progress", {
                        lengthComputable: !0,
                        loaded: ub - o.uploadedBytes,
                        total: ub - o.uploadedBytes
                    }), o), options.uploadedBytes = o.uploadedBytes = ub, o.result = result, o.textStatus = textStatus, o.jqXHR = jqXHR, that._trigger("chunkdone", null, o), that._trigger("chunkalways", null, o), fs > ub ? upload() : dfd.resolveWith(o.context, [result, textStatus, jqXHR])
                }).fail(function (jqXHR, textStatus, errorThrown) {
                    o.jqXHR = jqXHR, o.textStatus = textStatus, o.errorThrown = errorThrown, that._trigger("chunkfail", null, o), that._trigger("chunkalways", null, o), dfd.rejectWith(o.context, [jqXHR, textStatus, errorThrown])
                })
            }, this._enhancePromise(promise), promise.abort = function () {
                return jqXHR.abort()
            }, upload(), promise) : !1
        },
        _beforeSend: function (e, data) {
            0 === this._active && (this._trigger("start"), this._bitrateTimer = new this._BitrateTimer, this._progress.loaded = this._progress.total = 0, this._progress.bitrate = 0), this._initResponseObject(data), this._initProgressObject(data), data._progress.loaded = data.loaded = data.uploadedBytes || 0, data._progress.total = data.total = this._getTotal(data.files) || 1, data._progress.bitrate = data.bitrate = 0, this._active += 1, this._progress.loaded += data.loaded, this._progress.total += data.total
        },
        _onDone: function (result, textStatus, jqXHR, options) {
            var total = options._progress.total,
                response = options._response;
            options._progress.loaded < total && this._onProgress($.Event("progress", {
                lengthComputable: !0,
                loaded: total,
                total: total
            }), options), response.result = options.result = result, response.textStatus = options.textStatus = textStatus, response.jqXHR = options.jqXHR = jqXHR, this._trigger("done", null, options)
        },
        _onFail: function (jqXHR, textStatus, errorThrown, options) {
            var response = options._response;
            options.recalculateProgress && (this._progress.loaded -= options._progress.loaded, this._progress.total -= options._progress.total), response.jqXHR = options.jqXHR = jqXHR, response.textStatus = options.textStatus = textStatus, response.errorThrown = options.errorThrown = errorThrown, this._trigger("fail", null, options)
        },
        _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) {
            this._trigger("always", null, options)
        },
        _onSend: function (e, data) {
            data.submit || this._addConvenienceMethods(e, data);
            var jqXHR, aborted, slot, pipe, that = this,
                options = that._getAJAXSettings(data),
                send = function () {
                    return that._sending += 1, options._bitrateTimer = new that._BitrateTimer, jqXHR = jqXHR || ((aborted || that._trigger("send", e, options) === !1) && that._getXHRPromise(!1, options.context, aborted) || that._chunkedUpload(options) || $.ajax(options)).done(function (result, textStatus, jqXHR) {
                        that._onDone(result, textStatus, jqXHR, options)
                    }).fail(function (jqXHR, textStatus, errorThrown) {
                        that._onFail(jqXHR, textStatus, errorThrown, options)
                    }).always(function (jqXHRorResult, textStatus, jqXHRorError) {
                        if (that._onAlways(jqXHRorResult, textStatus, jqXHRorError, options), that._sending -= 1, that._active -= 1, options.limitConcurrentUploads && options.limitConcurrentUploads > that._sending)
                            for (var nextSlot = that._slots.shift(); nextSlot;) {
                                if ("pending" === that._getDeferredState(nextSlot)) {
                                    nextSlot.resolve();
                                    break
                                }
                                nextSlot = that._slots.shift()
                            }
                        0 === that._active && that._trigger("stop")
                    })
                };
            return this._beforeSend(e, options), this.options.sequentialUploads || this.options.limitConcurrentUploads && this.options.limitConcurrentUploads <= this._sending ? (this.options.limitConcurrentUploads > 1 ? (slot = $.Deferred(), this._slots.push(slot), pipe = slot.pipe(send)) : pipe = this._sequence = this._sequence.pipe(send, send), pipe.abort = function () {
                return aborted = [void 0, "abort", "abort"], jqXHR ? jqXHR.abort() : (slot && slot.rejectWith(options.context, aborted), send())
            }, this._enhancePromise(pipe)) : send()
        },
        _onAdd: function (e, data) {
            var paramNameSet, paramNameSlice, fileSet, i, that = this,
                result = !0,
                options = $.extend({}, this.options, data),
                limit = options.limitMultiFileUploads,
                paramName = this._getParamName(options);
            if ((options.singleFileUploads || limit) && this._isXHRUpload(options))
                if (!options.singleFileUploads && limit)
                    for (fileSet = [], paramNameSet = [], i = 0; i < data.files.length; i += limit) fileSet.push(data.files.slice(i, i + limit)), paramNameSlice = paramName.slice(i, i + limit), paramNameSlice.length || (paramNameSlice = paramName), paramNameSet.push(paramNameSlice);
                else paramNameSet = paramName;
            else fileSet = [data.files], paramNameSet = [paramName];
            return data.originalFiles = data.files, $.each(fileSet || data.files, function (index, element) {
                var newData = $.extend({}, data);
                return newData.files = fileSet ? element : [element], newData.paramName = paramNameSet[index], that._initResponseObject(newData), that._initProgressObject(newData), that._addConvenienceMethods(e, newData), result = that._trigger("add", e, newData)
            }), result
        },
        _replaceFileInput: function (input) {
            var inputClone = input.clone(!0);
            $("<form></form>").append(inputClone)[0].reset(), input.after(inputClone).detach(), $.cleanData(input.unbind("remove")), this.options.fileInput = this.options.fileInput.map(function (i, el) {
                return el === input[0] ? inputClone[0] : el
            }), input[0] === this.element[0] && (this.element = inputClone)
        },
        _handleFileTreeEntry: function (entry, path) {
            var dirReader, that = this,
                dfd = $.Deferred(),
                errorHandler = function (e) {
                    e && !e.entry && (e.entry = entry), dfd.resolve([e])
                };
            return path = path || "", entry.isFile ? entry._file ? (entry._file.relativePath = path, dfd.resolve(entry._file)) : entry.file(function (file) {
                file.relativePath = path, dfd.resolve(file)
            }, errorHandler) : entry.isDirectory ? (dirReader = entry.createReader(), dirReader.readEntries(function (entries) {
                that._handleFileTreeEntries(entries, path + entry.name + "/").done(function (files) {
                    dfd.resolve(files)
                }).fail(errorHandler)
            }, errorHandler)) : dfd.resolve([]), dfd.promise()
        },
        _handleFileTreeEntries: function (entries, path) {
            var that = this;
            return $.when.apply($, $.map(entries, function (entry) {
                return that._handleFileTreeEntry(entry, path)
            })).pipe(function () {
                return Array.prototype.concat.apply([], arguments)
            })
        },
        _getDroppedFiles: function (dataTransfer) {
            dataTransfer = dataTransfer || {};
            var items = dataTransfer.items;
            return items && items.length && (items[0].webkitGetAsEntry || items[0].getAsEntry) ? this._handleFileTreeEntries($.map(items, function (item) {
                var entry;
                return item.webkitGetAsEntry ? (entry = item.webkitGetAsEntry(), entry && (entry._file = item.getAsFile()), entry) : item.getAsEntry()
            })) : $.Deferred().resolve($.makeArray(dataTransfer.files)).promise()
        },
        _getSingleFileInputFiles: function (fileInput) {
            fileInput = $(fileInput);
            var files, value, entries = fileInput.prop("webkitEntries") || fileInput.prop("entries");
            if (entries && entries.length) return this._handleFileTreeEntries(entries);
            if (files = $.makeArray(fileInput.prop("files")), files.length) void 0 === files[0].name && files[0].fileName && $.each(files, function (index, file) {
                file.name = file.fileName, file.size = file.fileSize
            });
            else {
                if (value = fileInput.prop("value"), !value) return $.Deferred().resolve([]).promise();
                files = [{
                    name: value.replace(/^.*\\/, "")
                }]
            }
            return $.Deferred().resolve(files).promise()
        },
        _getFileInputFiles: function (fileInput) {
            return fileInput instanceof $ && 1 !== fileInput.length ? $.when.apply($, $.map(fileInput, this._getSingleFileInputFiles)).pipe(function () {
                return Array.prototype.concat.apply([], arguments)
            }) : this._getSingleFileInputFiles(fileInput)
        },
        _onChange: function (e) {
            var that = this,
                data = {
                    fileInput: $(e.target),
                    form: $(e.target.form)
                };
            this._getFileInputFiles(data.fileInput).always(function (files) {
                data.files = files, that.options.replaceFileInput && that._replaceFileInput(data.fileInput), that._trigger("change", e, data) !== !1 && that._onAdd(e, data)
            })
        },
        _onPaste: function (e) {
            var items = e.originalEvent && e.originalEvent.clipboardData && e.originalEvent.clipboardData.items,
                data = {
                    files: []
                };
            return items && items.length && ($.each(items, function (index, item) {
                var file = item.getAsFile && item.getAsFile();
                file && data.files.push(file)
            }), this._trigger("paste", e, data) === !1 || this._onAdd(e, data) === !1) ? !1 : void 0
        },
        _onDrop: function (e) {
            var that = this,
                dataTransfer = e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer,
                data = {};
            dataTransfer && dataTransfer.files && dataTransfer.files.length && (e.preventDefault(), this._getDroppedFiles(dataTransfer).always(function (files) {
                data.files = files, that._trigger("drop", e, data) !== !1 && that._onAdd(e, data)
            }))
        },
        _onDragOver: function (e) {
            var dataTransfer = e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;
            if (dataTransfer) {
                if (this._trigger("dragover", e) === !1) return !1; - 1 !== $.inArray("Files", dataTransfer.types) && (dataTransfer.dropEffect = "copy", e.preventDefault())
            }
        },
        _initEventHandlers: function () {
            this._isXHRUpload(this.options) && (this._on(this.options.dropZone, {
                dragover: this._onDragOver,
                drop: this._onDrop
            }), this._on(this.options.pasteZone, {
                paste: this._onPaste
            })), this._on(this.options.fileInput, {
                change: this._onChange
            })
        },
        _destroyEventHandlers: function () {
            this._off(this.options.dropZone, "dragover drop"), this._off(this.options.pasteZone, "paste"), this._off(this.options.fileInput, "change")
        },
        _setOption: function (key, value) {
            var reinit = -1 !== $.inArray(key, this._specialOptions);
            reinit && this._destroyEventHandlers(), this._super(key, value), reinit && (this._initSpecialOptions(), this._initEventHandlers())
        },
        _initSpecialOptions: function () {
            var options = this.options;
            void 0 === options.fileInput ? options.fileInput = this.element.is('input[type="file"]') ? this.element : this.element.find('input[type="file"]') : options.fileInput instanceof $ || (options.fileInput = $(options.fileInput)), options.dropZone instanceof $ || (options.dropZone = $(options.dropZone)), options.pasteZone instanceof $ || (options.pasteZone = $(options.pasteZone))
        },
        _getRegExp: function (str) {
            var parts = str.split("/"),
                modifiers = parts.pop();
            return parts.shift(), new RegExp(parts.join("/"), modifiers)
        },
        _isRegExpOption: function (key, value) {
            return "url" !== key && "string" === $.type(value) && /^\/.*\/[igm]{0,3}$/.test(value)
        },
        _initDataAttributes: function () {
            var that = this,
                options = this.options;
            $.each($(this.element[0].cloneNode(!1)).data(), function (key, value) {
                that._isRegExpOption(key, value) && (value = that._getRegExp(value)), options[key] = value
            })
        },
        _create: function () {
            this._initDataAttributes(), this._initSpecialOptions(), this._slots = [], this._sequence = this._getXHRPromise(!0), this._sending = this._active = 0, this._initProgressObject(this), this._initEventHandlers()
        },
        active: function () {
            return this._active
        },
        progress: function () {
            return this._progress
        },
        add: function (data) {
            var that = this;
            data && !this.options.disabled && (data.fileInput && !data.files ? this._getFileInputFiles(data.fileInput).always(function (files) {
                data.files = files, that._onAdd(null, data)
            }) : (data.files = $.makeArray(data.files), this._onAdd(null, data)))
        },
        send: function (data) {
            if (data && !this.options.disabled) {
                if (data.fileInput && !data.files) {
                    var jqXHR, aborted, that = this,
                        dfd = $.Deferred(),
                        promise = dfd.promise();
                    return promise.abort = function () {
                        return aborted = !0, jqXHR ? jqXHR.abort() : (dfd.reject(null, "abort", "abort"), promise)
                    }, this._getFileInputFiles(data.fileInput).always(function (files) {
                        aborted || (data.files = files, jqXHR = that._onSend(null, data).then(function (result, textStatus, jqXHR) {
                            dfd.resolve(result, textStatus, jqXHR)
                        }, function (jqXHR, textStatus, errorThrown) {
                            dfd.reject(jqXHR, textStatus, errorThrown)
                        }))
                    }), this._enhancePromise(promise)
                }
                if (data.files = $.makeArray(data.files), data.files.length) return this._onSend(null, data)
            }
            return this._getXHRPromise(!1, data && data.context)
        }
    })
});
var jstz = function () {
    var b = function (a) {
            return a = -a.getTimezoneOffset(), null !== a ? a : 0
        },
        c = function () {
            return b(new Date(2010, 0, 1, 0, 0, 0, 0))
        },
        f = function () {
            return b(new Date(2010, 5, 1, 0, 0, 0, 0))
        },
        e = function () {
            var a = c(),
                d = f(),
                b = c() - f();
            return new jstz.TimeZone(jstz.olson.timezones[0 > b ? a + ",1" : b > 0 ? d + ",1,s" : a + ",0"])
        };
    return {
        determine_timezone: function () {
            return "undefined" != typeof console && console.log("jstz.determine_timezone() is deprecated and will be removed in an upcoming version. Please use jstz.determine() instead."), e()
        },
        determine: e,
        date_is_dst: function (a) {
            var d = 5 < a.getMonth() ? f() : c(),
                a = b(a);
            return 0 !== d - a
        }
    }
}();
jstz.TimeZone = function (b) {
    var c = null,
        c = b;
    return "undefined" != typeof jstz.olson.ambiguity_list[c] && function () {
        for (var b = jstz.olson.ambiguity_list[c], e = b.length, a = 0, d = b[0]; e > a; a += 1)
            if (d = b[a], jstz.date_is_dst(jstz.olson.dst_start_dates[d])) {
                c = d;
                break
            }
    }(), {
        name: function () {
            return c
        }
    }
}, jstz.olson = {}, jstz.olson.timezones = {
    "-720,0": "Etc/GMT+12",
    "-660,0": "Pacific/Pago_Pago",
    "-600,1": "America/Adak",
    "-600,0": "Pacific/Honolulu",
    "-570,0": "Pacific/Marquesas",
    "-540,0": "Pacific/Gambier",
    "-540,1": "America/Anchorage",
    "-480,1": "America/Los_Angeles",
    "-480,0": "Pacific/Pitcairn",
    "-420,0": "America/Phoenix",
    "-420,1": "America/Denver",
    "-360,0": "America/Guatemala",
    "-360,1": "America/Chicago",
    "-360,1,s": "Pacific/Easter",
    "-300,0": "America/Bogota",
    "-300,1": "America/New_York",
    "-270,0": "America/Caracas",
    "-240,1": "America/Halifax",
    "-240,0": "America/Santo_Domingo",
    "-240,1,s": "America/Asuncion",
    "-210,1": "America/St_Johns",
    "-180,1": "America/Godthab",
    "-180,0": "America/Argentina/Buenos_Aires",
    "-180,1,s": "America/Montevideo",
    "-120,0": "America/Noronha",
    "-120,1": "Etc/GMT+2",
    "-60,1": "Atlantic/Azores",
    "-60,0": "Atlantic/Cape_Verde",
    "0,0": "Etc/UTC",
    "0,1": "Europe/London",
    "60,1": "Europe/Berlin",
    "60,0": "Africa/Lagos",
    "60,1,s": "Africa/Windhoek",
    "120,1": "Asia/Beirut",
    "120,0": "Africa/Johannesburg",
    "180,1": "Europe/Moscow",
    "180,0": "Asia/Baghdad",
    "210,1": "Asia/Tehran",
    "240,0": "Asia/Dubai",
    "240,1": "Asia/Yerevan",
    "270,0": "Asia/Kabul",
    "300,1": "Asia/Yekaterinburg",
    "300,0": "Asia/Karachi",
    "330,0": "Asia/Kolkata",
    "345,0": "Asia/Kathmandu",
    "360,0": "Asia/Dhaka",
    "360,1": "Asia/Omsk",
    "390,0": "Asia/Rangoon",
    "420,1": "Asia/Krasnoyarsk",
    "420,0": "Asia/Jakarta",
    "480,0": "Asia/Shanghai",
    "480,1": "Asia/Irkutsk",
    "525,0": "Australia/Eucla",
    "525,1,s": "Australia/Eucla",
    "540,1": "Asia/Yakutsk",
    "540,0": "Asia/Tokyo",
    "570,0": "Australia/Darwin",
    "570,1,s": "Australia/Adelaide",
    "600,0": "Australia/Brisbane",
    "600,1": "Asia/Vladivostok",
    "600,1,s": "Australia/Sydney",
    "630,1,s": "Australia/Lord_Howe",
    "660,1": "Asia/Kamchatka",
    "660,0": "Pacific/Noumea",
    "690,0": "Pacific/Norfolk",
    "720,1,s": "Pacific/Auckland",
    "720,0": "Pacific/Tarawa",
    "765,1,s": "Pacific/Chatham",
    "780,0": "Pacific/Tongatapu",
    "780,1,s": "Pacific/Apia",
    "840,0": "Pacific/Kiritimati"
}, jstz.olson.dst_start_dates = {
    "America/Denver": new Date(2011, 2, 13, 3, 0, 0, 0),
    "America/Mazatlan": new Date(2011, 3, 3, 3, 0, 0, 0),
    "America/Chicago": new Date(2011, 2, 13, 3, 0, 0, 0),
    "America/Mexico_City": new Date(2011, 3, 3, 3, 0, 0, 0),
    "Atlantic/Stanley": new Date(2011, 8, 4, 7, 0, 0, 0),
    "America/Asuncion": new Date(2011, 9, 2, 3, 0, 0, 0),
    "America/Santiago": new Date(2011, 9, 9, 3, 0, 0, 0),
    "America/Campo_Grande": new Date(2011, 9, 16, 5, 0, 0, 0),
    "America/Montevideo": new Date(2011, 9, 2, 3, 0, 0, 0),
    "America/Sao_Paulo": new Date(2011, 9, 16, 5, 0, 0, 0),
    "America/Los_Angeles": new Date(2011, 2, 13, 8, 0, 0, 0),
    "America/Santa_Isabel": new Date(2011, 3, 5, 8, 0, 0, 0),
    "America/Havana": new Date(2011, 2, 13, 2, 0, 0, 0),
    "America/New_York": new Date(2011, 2, 13, 7, 0, 0, 0),
    "Asia/Gaza": new Date(2011, 2, 26, 23, 0, 0, 0),
    "Asia/Beirut": new Date(2011, 2, 27, 1, 0, 0, 0),
    "Europe/Minsk": new Date(2011, 2, 27, 2, 0, 0, 0),
    "Europe/Helsinki": new Date(2011, 2, 27, 4, 0, 0, 0),
    "Europe/Istanbul": new Date(2011, 2, 28, 5, 0, 0, 0),
    "Asia/Damascus": new Date(2011, 3, 1, 2, 0, 0, 0),
    "Asia/Jerusalem": new Date(2011, 3, 1, 6, 0, 0, 0),
    "Africa/Cairo": new Date(2010, 3, 30, 4, 0, 0, 0),
    "Asia/Yerevan": new Date(2011, 2, 27, 4, 0, 0, 0),
    "Asia/Baku": new Date(2011, 2, 27, 8, 0, 0, 0),
    "Pacific/Auckland": new Date(2011, 8, 26, 7, 0, 0, 0),
    "Pacific/Fiji": new Date(2010, 11, 29, 23, 0, 0, 0),
    "America/Halifax": new Date(2011, 2, 13, 6, 0, 0, 0),
    "America/Goose_Bay": new Date(2011, 2, 13, 2, 1, 0, 0),
    "America/Miquelon": new Date(2011, 2, 13, 5, 0, 0, 0),
    "America/Godthab": new Date(2011, 2, 27, 1, 0, 0, 0)
}, jstz.olson.ambiguity_list = {
    "America/Denver": ["America/Denver", "America/Mazatlan"],
    "America/Chicago": ["America/Chicago", "America/Mexico_City"],
    "America/Asuncion": ["Atlantic/Stanley", "America/Asuncion", "America/Santiago", "America/Campo_Grande"],
    "America/Montevideo": ["America/Montevideo", "America/Sao_Paulo"],
    "Asia/Beirut": "Asia/Gaza Asia/Beirut Europe/Minsk Europe/Helsinki Europe/Istanbul Asia/Damascus Asia/Jerusalem Africa/Cairo".split(" "),
    "Asia/Yerevan": ["Asia/Yerevan", "Asia/Baku"],
    "Pacific/Auckland": ["Pacific/Auckland", "Pacific/Fiji"],
    "America/Los_Angeles": ["America/Los_Angeles", "America/Santa_Isabel"],
    "America/New_York": ["America/Havana", "America/New_York"],
    "America/Halifax": ["America/Goose_Bay", "America/Halifax"],
    "America/Godthab": ["America/Miquelon", "America/Godthab"]
},
function (a) {
    function b(q, g) {
        function c() {
            return k.update(), s(), k
        }

        function w() {
            var z = v.toLowerCase();
            p.obj.css(n, r / d.ratio), h.obj.css(n, -r), o.start = p.obj.offset()[n], d.obj.css(z, m[g.axis]), m.obj.css(z, m[g.axis]), p.obj.css(z, p[g.axis])
        }

        function s() {
            e ? j.obj[0].ontouchstart = function (z) {
                1 === z.touches.length && (i(z.touches[0]), z.stopPropagation())
            } : (p.obj.bind("mousedown", i), m.obj.bind("mouseup", u)), g.scroll && window.addEventListener ? (t[0].addEventListener("DOMMouseScroll", x, !1), t[0].addEventListener("mousewheel", x, !1), t[0].addEventListener("MozMousePixelScroll", function (z) {
                z.preventDefault()
            }, !1)) : g.scroll && (t[0].onmousewheel = x)
        }

        function i(A) {
            a("body").addClass("noSelect");
            var z = parseInt(p.obj.css(n), 10);
            o.start = l ? A.pageX : A.pageY, y.start = "auto" == z ? 0 : z, e ? (document.ontouchmove = function (B) {
                B.preventDefault(), u(B.touches[0])
            }, document.ontouchend = f) : (a(document).bind("mousemove", u), a(document).bind("mouseup", f), p.obj.bind("mouseup", f))
        }

        function x(B) {
            if (h.ratio < 1) {
                var A = B || window.event,
                    z = A.wheelDelta ? A.wheelDelta / 120 : -A.detail / 3;
                r -= z * g.wheel, r = Math.min(h[g.axis] - j[g.axis], Math.max(0, r)), p.obj.css(n, r / d.ratio), h.obj.css(n, -r), (g.lockscroll || r !== h[g.axis] - j[g.axis] && 0 !== r) && (A = a.event.fix(A), A.preventDefault())
            }
        }

        function u(z) {
            h.ratio < 1 && (y.now = g.invertscroll && e ? Math.min(m[g.axis] - p[g.axis], Math.max(0, y.start + (o.start - (l ? z.pageX : z.pageY)))) : Math.min(m[g.axis] - p[g.axis], Math.max(0, y.start + ((l ? z.pageX : z.pageY) - o.start))), r = y.now * d.ratio, h.obj.css(n, -r), p.obj.css(n, y.now))
        }

        function f() {
            a("body").removeClass("noSelect"), a(document).unbind("mousemove", u), a(document).unbind("mouseup", f), p.obj.unbind("mouseup", f), document.ontouchmove = document.ontouchend = null
        }
        var k = this,
            t = q,
            j = {
                obj: a(".viewport", q)
            },
            h = {
                obj: a(".overview", q)
            },
            d = {
                obj: a(".scrollbar", q)
            },
            m = {
                obj: a(".track", d.obj)
            },
            p = {
                obj: a(".thumb", d.obj)
            },
            l = "x" === g.axis,
            n = l ? "left" : "top",
            v = l ? "Width" : "Height",
            r = 0,
            y = {
                start: 0,
                now: 0
            },
            o = {},
            e = "ontouchstart" in document.documentElement;
        return this.update = function (z) {
            j[g.axis] = j.obj[0]["offset" + v], h[g.axis] = h.obj[0]["scroll" + v], h.ratio = j[g.axis] / h[g.axis], d.obj.toggleClass("disable", h.ratio >= 1), m[g.axis] = "auto" === g.size ? j[g.axis] : g.size, p[g.axis] = Math.min(m[g.axis], Math.max(0, "auto" === g.sizethumb ? m[g.axis] * h.ratio : g.sizethumb)), d.ratio = "auto" === g.sizethumb ? h[g.axis] / m[g.axis] : (h[g.axis] - j[g.axis]) / (m[g.axis] - p[g.axis]), r = "relative" === z && h.ratio <= 1 ? Math.min(h[g.axis] - j[g.axis], Math.max(0, r)) : 0, r = "bottom" === z && h.ratio <= 1 ? h[g.axis] - j[g.axis] : isNaN(parseInt(z, 10)) ? r : parseInt(z, 10), w()
        }, c()
    }
    a.tiny = a.tiny || {}, a.tiny.scrollbar = {
        options: {
            axis: "y",
            wheel: 40,
            scroll: !0,
            lockscroll: !0,
            size: "auto",
            sizethumb: "auto",
            invertscroll: !1
        }
    }, a.fn.tinyscrollbar = function (d) {
        var c = a.extend({}, a.tiny.scrollbar.options, d);
        return this.each(function () {
            a(this).data("tsb", new b(a(this), c))
        }), this
    }, a.fn.tinyscrollbar_update = function (c) {
        return a(this).data("tsb").update(c)
    }
}(jQuery), ! function (a) {
    a(function () {
        a.support.transition = function () {
            var a = function () {
                var c, a = document.createElement("bootstrap"),
                    b = {
                        WebkitTransition: "webkitTransitionEnd",
                        MozTransition: "transitionend",
                        OTransition: "oTransitionEnd otransitionend",
                        transition: "transitionend"
                    };
                for (c in b)
                    if (void 0 !== a.style[c]) return b[c]
            }();
            return a && {
                end: a
            }
        }()
    })
}(window.jQuery), ! function (a) {
    var b = function (b, c) {
        this.options = c, this.$element = a(b).delegate('[data-dismiss="modal"]', "click.dismiss.modal", a.proxy(this.hide, this)), this.options.remote && this.$element.find(".modal-body").load(this.options.remote)
    };
    b.prototype = {
        constructor: b,
        toggle: function () {
            return this[this.isShown ? "hide" : "show"]()
        },
        show: function () {
            var b = this,
                c = a.Event("show");
            this.$element.trigger(c), this.isShown || c.isDefaultPrevented() || (this.isShown = !0, this.escape(), this.backdrop(function () {
                var c = a.support.transition && b.$element.hasClass("fade");
                b.$element.parent().length || b.$element.appendTo(document.body), b.$element.show(), c && b.$element[0].offsetWidth, b.$element.addClass("in").attr("aria-hidden", !1), b.enforceFocus(), c ? b.$element.one(a.support.transition.end, function () {
                    b.$element.focus().trigger("shown")
                }) : b.$element.focus().trigger("shown")
            }))
        },
        hide: function (b) {
            b && b.preventDefault(), b = a.Event("hide"), this.$element.trigger(b), this.isShown && !b.isDefaultPrevented() && (this.isShown = !1, this.escape(), a(document).off("focusin.modal"), this.$element.removeClass("in").attr("aria-hidden", !0), a.support.transition && this.$element.hasClass("fade") ? this.hideWithTransition() : this.hideModal())
        },
        enforceFocus: function () {
            var b = this;
            a(document).on("focusin.modal", function (a) {
                b.$element[0] !== a.target && !b.$element.has(a.target).length && b.$element.focus()
            })
        },
        escape: function () {
            var a = this;
            this.isShown && this.options.keyboard ? this.$element.on("keyup.dismiss.modal", function (b) {
                27 == b.which && a.hide()
            }) : this.isShown || this.$element.off("keyup.dismiss.modal")
        },
        hideWithTransition: function () {
            var b = this,
                c = setTimeout(function () {
                    b.$element.off(a.support.transition.end), b.hideModal()
                }, 500);
            this.$element.one(a.support.transition.end, function () {
                clearTimeout(c), b.hideModal()
            })
        },
        hideModal: function () {
            var a = this;
            this.$element.hide(), this.backdrop(function () {
                a.removeBackdrop(), a.$element.trigger("hidden")
            })
        },
        removeBackdrop: function () {
            this.$backdrop.remove(), this.$backdrop = null
        },
        backdrop: function (b) {
            var d = this.$element.hasClass("fade") ? "fade" : "";
            if (this.isShown && this.options.backdrop) {
                var e = a.support.transition && d;
                if (this.$backdrop = a('<div class="modal-backdrop ' + d + '" />').appendTo(document.body), this.$backdrop.click("static" == this.options.backdrop ? a.proxy(this.$element[0].focus, this.$element[0]) : a.proxy(this.hide, this)), e && this.$backdrop[0].offsetWidth, this.$backdrop.addClass("in"), !b) return;
                e ? this.$backdrop.one(a.support.transition.end, b) : b()
            } else !this.isShown && this.$backdrop ? (this.$backdrop.removeClass("in"), a.support.transition && this.$element.hasClass("fade") ? this.$backdrop.one(a.support.transition.end, b) : b()) : b && b()
        }
    };
    var c = a.fn.modal;
    a.fn.modal = function (c) {
        return this.each(function () {
            var d = a(this),
                e = d.data("modal"),
                f = a.extend({}, a.fn.modal.defaults, d.data(), "object" == typeof c && c);
            e || d.data("modal", e = new b(this, f)), "string" == typeof c ? e[c]() : f.show && e.show()
        })
    }, a.fn.modal.defaults = {
        backdrop: !0,
        keyboard: !0,
        show: !0
    }, a.fn.modal.Constructor = b, a.fn.modal.noConflict = function () {
        return a.fn.modal = c, this
    }, a(document).on("click.modal.data-api", '[data-toggle="modal"]', function (b) {
        var c = a(this),
            d = c.attr("href"),
            e = a(c.attr("data-target") || d && d.replace(/.*(?=#[^\s]+$)/, "")),
            f = e.data("modal") ? "toggle" : a.extend({
                remote: !/#/.test(d) && d
            }, e.data(), c.data());
        b.preventDefault(), e.modal(f).one("hide", function () {
            c.focus()
        })
    })
}(window.jQuery), ! function (a) {
    function b(b, c) {
        var f, d = a.proxy(this.process, this),
            e = a(b).is("body") ? a(window) : a(b);
        this.options = a.extend({}, a.fn.scrollspy.defaults, c), this.$scrollElement = e.on("scroll.scroll-spy.data-api", d), this.selector = (this.options.target || (f = a(b).attr("href")) && f.replace(/.*(?=#[^\s]+$)/, "") || "") + " .nav li > a", this.$body = a("body"), this.refresh(), this.process()
    }
    b.prototype = {
        constructor: b,
        refresh: function () {
            var c, b = this;
            this.offsets = a([]), this.targets = a([]), c = this.$body.find(this.selector).map(function () {
                var c = a(this),
                    d = c.data("target") || c.attr("href"),
                    e = /^#\w/.test(d) && a(d);
                return e && e.length && [
                    [e.position().top + (!a.isWindow(b.$scrollElement.get(0)) && b.$scrollElement.scrollTop()), d]
                ] || null
            }).sort(function (a, b) {
                return a[0] - b[0]
            }).each(function () {
                b.offsets.push(this[0]), b.targets.push(this[1])
            })
        },
        process: function () {
            var g, a = this.$scrollElement.scrollTop() + this.options.offset,
                b = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight,
                c = b - this.$scrollElement.height(),
                d = this.offsets,
                e = this.targets,
                f = this.activeTarget;
            if (a >= c) return f != (g = e.last()[0]) && this.activate(g);
            for (g = d.length; g--;) f != e[g] && a >= d[g] && (!d[g + 1] || a <= d[g + 1]) && this.activate(e[g])
        },
        activate: function (b) {
            var c, d;
            this.activeTarget = b, a(this.selector).parent(".active").removeClass("active"), d = this.selector + '[data-target="' + b + '"],' + this.selector + '[href="' + b + '"]', c = a(d).parent("li").addClass("active"), c.parent(".dropdown-menu").length && (c = c.closest("li.dropdown").addClass("active")), c.trigger("activate")
        }
    };
    var c = a.fn.scrollspy;
    a.fn.scrollspy = function (c) {
        return this.each(function () {
            var d = a(this),
                e = d.data("scrollspy"),
                f = "object" == typeof c && c;
            e || d.data("scrollspy", e = new b(this, f)), "string" == typeof c && e[c]()
        })
    }, a.fn.scrollspy.Constructor = b, a.fn.scrollspy.defaults = {
        offset: 10
    }, a.fn.scrollspy.noConflict = function () {
        return a.fn.scrollspy = c, this
    }, a(window).on("load", function () {
        a('[data-spy="scroll"]').each(function () {
            var b = a(this);
            b.scrollspy(b.data())
        })
    })
}(window.jQuery), ! function (a) {
    var b = function (b) {
        this.element = a(b)
    };
    b.prototype = {
        constructor: b,
        show: function () {
            var e, f, g, b = this.element,
                c = b.closest("ul:not(.dropdown-menu)"),
                d = b.attr("data-target");
            d || (d = b.attr("href"), d = d && d.replace(/.*(?=#[^\s]*$)/, "")), b.parent("li").hasClass("active") || (e = c.find(".active:last a")[0], g = a.Event("show", {
                relatedTarget: e
            }), b.trigger(g), g.isDefaultPrevented() || (f = a(d), this.activate(b.parent("li"), c), this.activate(f, f.parent(), function () {
                b.trigger({
                    type: "shown",
                    relatedTarget: e
                })
            })))
        },
        activate: function (b, c, d) {
            function g() {
                e.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"), b.addClass("active"), f ? (b[0].offsetWidth, b.addClass("in")) : b.removeClass("fade"), b.parent(".dropdown-menu") && b.closest("li.dropdown").addClass("active"), d && d()
            }
            var e = c.find("> .active"),
                f = d && a.support.transition && e.hasClass("fade");
            f ? e.one(a.support.transition.end, g) : g(), e.removeClass("in")
        }
    };
    var c = a.fn.tab;
    a.fn.tab = function (c) {
        return this.each(function () {
            var d = a(this),
                e = d.data("tab");
            e || d.data("tab", e = new b(this)), "string" == typeof c && e[c]()
        })
    }, a.fn.tab.Constructor = b, a.fn.tab.noConflict = function () {
        return a.fn.tab = c, this
    }, a(document).on("click.tab.data-api", '[data-toggle="tab"], [data-toggle="pill"]', function (b) {
        b.preventDefault(), a(this).tab("show")
    })
}(window.jQuery), ! function (a) {
    var b = function (a, b) {
        this.init("tooltip", a, b)
    };
    b.prototype = {
        constructor: b,
        init: function (b, c, d) {
            var e, f, g, h, i;
            for (this.type = b, this.$element = a(c), this.options = this.getOptions(d), this.enabled = !0, g = this.options.trigger.split(" "), i = g.length; i--;) h = g[i], "click" == h ? this.$element.on("click." + this.type, this.options.selector, a.proxy(this.toggle, this)) : "manual" != h && (e = "hover" == h ? "mouseenter" : "focus", f = "hover" == h ? "mouseleave" : "blur", this.$element.on(e + "." + this.type, this.options.selector, a.proxy(this.enter, this)), this.$element.on(f + "." + this.type, this.options.selector, a.proxy(this.leave, this)));
            this.options.selector ? this._options = a.extend({}, this.options, {
                trigger: "manual",
                selector: ""
            }) : this.fixTitle()
        },
        getOptions: function (b) {
            return b = a.extend({}, a.fn[this.type].defaults, this.$element.data(), b), b.delay && "number" == typeof b.delay && (b.delay = {
                show: b.delay,
                hide: b.delay
            }), b
        },
        enter: function (b) {
            var c = a(b.currentTarget)[this.type](this._options).data(this.type);
            return c.options.delay && c.options.delay.show ? (clearTimeout(this.timeout), c.hoverState = "in", this.timeout = setTimeout(function () {
                "in" == c.hoverState && c.show()
            }, c.options.delay.show), void 0) : c.show()
        },
        leave: function (b) {
            var c = a(b.currentTarget)[this.type](this._options).data(this.type);
            return this.timeout && clearTimeout(this.timeout), c.options.delay && c.options.delay.hide ? (c.hoverState = "out", this.timeout = setTimeout(function () {
                "out" == c.hoverState && c.hide()
            }, c.options.delay.hide), void 0) : c.hide()
        },
        show: function () {
            var b, c, d, e, f, g, h = a.Event("show");
            if (this.hasContent() && this.enabled) {
                if (this.$element.trigger(h), h.isDefaultPrevented()) return;
                switch (b = this.tip(), this.setContent(), this.options.animation && b.addClass("fade"), f = "function" == typeof this.options.placement ? this.options.placement.call(this, b[0], this.$element[0]) : this.options.placement, b.detach().css({
                    top: 0,
                    left: 0,
                    display: "block"
                }), this.options.container ? b.appendTo(this.options.container) : b.insertAfter(this.$element), c = this.getPosition(), d = b[0].offsetWidth, e = b[0].offsetHeight, f) {
                case "bottom":
                    g = {
                        top: c.top + c.height,
                        left: c.left + c.width / 2 - d / 2
                    };
                    break;
                case "top":
                    g = {
                        top: c.top - e,
                        left: c.left + c.width / 2 - d / 2
                    };
                    break;
                case "left":
                    g = {
                        top: c.top + c.height / 2 - e / 2,
                        left: c.left - d
                    };
                    break;
                case "right":
                    g = {
                        top: c.top + c.height / 2 - e / 2,
                        left: c.left + c.width
                    }
                }
                this.applyPlacement(g, f), this.$element.trigger("shown")
            }
        },
        applyPlacement: function (a, b) {
            var f, g, h, i, c = this.tip(),
                d = c[0].offsetWidth,
                e = c[0].offsetHeight;
            c.offset(a).addClass(b).addClass("in"), f = c[0].offsetWidth, g = c[0].offsetHeight, "top" == b && g != e && (a.top = a.top + e - g, i = !0), "bottom" == b || "top" == b ? (h = 0, a.left < 0 && (h = -2 * a.left, a.left = 0, c.offset(a), f = c[0].offsetWidth, g = c[0].offsetHeight), this.replaceArrow(h - d + f, f, "left")) : this.replaceArrow(g - e, g, "top"), i && c.offset(a)
        },
        replaceArrow: function (a, b, c) {
            this.arrow().css(c, a ? 50 * (1 - a / b) + "%" : "")
        },
        setContent: function () {
            var a = this.tip(),
                b = this.getTitle();
            a.find(".tooltip-inner")[this.options.html ? "html" : "text"](b), a.removeClass("fade in top bottom left right")
        },
        hide: function () {
            function e() {
                var b = setTimeout(function () {
                    c.off(a.support.transition.end).detach()
                }, 500);
                c.one(a.support.transition.end, function () {
                    clearTimeout(b), c.detach()
                })
            }
            var c = this.tip(),
                d = a.Event("hide");
            return this.$element.trigger(d), d.isDefaultPrevented() ? void 0 : (c.removeClass("in"), a.support.transition && this.$tip.hasClass("fade") ? e() : c.detach(), this.$element.trigger("hidden"), this)
        },
        fixTitle: function () {
            var a = this.$element;
            (a.attr("title") || "string" != typeof a.attr("data-original-title")) && a.attr("data-original-title", a.attr("title") || "").attr("title", "")
        },
        hasContent: function () {
            return this.getTitle()
        },
        getPosition: function () {
            var b = this.$element[0];
            return a.extend({}, "function" == typeof b.getBoundingClientRect ? b.getBoundingClientRect() : {
                width: b.offsetWidth,
                height: b.offsetHeight
            }, this.$element.offset())
        },
        getTitle: function () {
            var a, b = this.$element,
                c = this.options;
            return a = b.attr("data-original-title") || ("function" == typeof c.title ? c.title.call(b[0]) : c.title)
        },
        tip: function () {
            return this.$tip = this.$tip || a(this.options.template)
        },
        arrow: function () {
            return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
        },
        validate: function () {
            this.$element[0].parentNode || (this.hide(), this.$element = null, this.options = null)
        },
        enable: function () {
            this.enabled = !0
        },
        disable: function () {
            this.enabled = !1
        },
        toggleEnabled: function () {
            this.enabled = !this.enabled
        },
        toggle: function (b) {
            var c = b ? a(b.currentTarget)[this.type](this._options).data(this.type) : this;
            c.tip().hasClass("in") ? c.hide() : c.show()
        },
        destroy: function () {
            this.hide().$element.off("." + this.type).removeData(this.type)
        }
    };
    var c = a.fn.tooltip;
    a.fn.tooltip = function (c) {
        return this.each(function () {
            var d = a(this),
                e = d.data("tooltip"),
                f = "object" == typeof c && c;
            e || d.data("tooltip", e = new b(this, f)), "string" == typeof c && e[c]()
        })
    }, a.fn.tooltip.Constructor = b, a.fn.tooltip.defaults = {
        animation: !0,
        placement: "top",
        selector: !1,
        template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
        trigger: "hover focus",
        title: "",
        delay: 0,
        html: !1,
        container: !1
    }, a.fn.tooltip.noConflict = function () {
        return a.fn.tooltip = c, this
    }
}(window.jQuery), ! function (a) {
    var b = function (a, b) {
        this.init("popover", a, b)
    };
    b.prototype = a.extend({}, a.fn.tooltip.Constructor.prototype, {
        constructor: b,
        setContent: function () {
            var a = this.tip(),
                b = this.getTitle(),
                c = this.getContent();
            a.find(".popover-title")[this.options.html ? "html" : "text"](b), a.find(".popover-content")[this.options.html ? "html" : "text"](c), a.removeClass("fade top bottom left right in")
        },
        hasContent: function () {
            return this.getTitle() || this.getContent()
        },
        getContent: function () {
            var a, b = this.$element,
                c = this.options;
            return a = ("function" == typeof c.content ? c.content.call(b[0]) : c.content) || b.attr("data-content")
        },
        tip: function () {
            return this.$tip || (this.$tip = a(this.options.template)), this.$tip
        },
        destroy: function () {
            this.hide().$element.off("." + this.type).removeData(this.type)
        }
    });
    var c = a.fn.popover;
    a.fn.popover = function (c) {
        return this.each(function () {
            var d = a(this),
                e = d.data("popover"),
                f = "object" == typeof c && c;
            e || d.data("popover", e = new b(this, f)), "string" == typeof c && e[c]()
        })
    }, a.fn.popover.Constructor = b, a.fn.popover.defaults = a.extend({}, a.fn.tooltip.defaults, {
        placement: "right",
        trigger: "click",
        content: "",
        template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
    }), a.fn.popover.noConflict = function () {
        return a.fn.popover = c, this
    }
}(window.jQuery), ! function (a) {
    var b = '[data-dismiss="alert"]',
        c = function (c) {
            a(c).on("click", b, this.close)
        };
    c.prototype.close = function (b) {
        function f() {
            e.trigger("closed").remove()
        }
        var e, c = a(this),
            d = c.attr("data-target");
        d || (d = c.attr("href"), d = d && d.replace(/.*(?=#[^\s]*$)/, "")), e = a(d), b && b.preventDefault(), e.length || (e = c.hasClass("alert") ? c : c.parent()), e.trigger(b = a.Event("close")), b.isDefaultPrevented() || (e.removeClass("in"), a.support.transition && e.hasClass("fade") ? e.on(a.support.transition.end, f) : f())
    };
    var d = a.fn.alert;
    a.fn.alert = function (b) {
        return this.each(function () {
            var d = a(this),
                e = d.data("alert");
            e || d.data("alert", e = new c(this)), "string" == typeof b && e[b].call(d)
        })
    }, a.fn.alert.Constructor = c, a.fn.alert.noConflict = function () {
        return a.fn.alert = d, this
    }, a(document).on("click.alert.data-api", b, c.prototype.close)
}(window.jQuery), ! function (a) {
    var b = function (b, c) {
        this.$element = a(b), this.options = a.extend({}, a.fn.button.defaults, c)
    };
    b.prototype.setState = function (a) {
        var b = "disabled",
            c = this.$element,
            d = c.data(),
            e = c.is("input") ? "val" : "html";
        a += "Text", d.resetText || c.data("resetText", c[e]()), c[e](d[a] || this.options[a]), setTimeout(function () {
            "loadingText" == a ? c.addClass(b).attr(b, b) : c.removeClass(b).removeAttr(b)
        }, 0)
    }, b.prototype.toggle = function () {
        var a = this.$element.closest('[data-toggle="buttons-radio"]');
        a && a.find(".active").removeClass("active"), this.$element.toggleClass("active")
    };
    var c = a.fn.button;
    a.fn.button = function (c) {
        return this.each(function () {
            var d = a(this),
                e = d.data("button"),
                f = "object" == typeof c && c;
            e || d.data("button", e = new b(this, f)), "toggle" == c ? e.toggle() : c && e.setState(c)
        })
    }, a.fn.button.defaults = {
        loadingText: "loading..."
    }, a.fn.button.Constructor = b, a.fn.button.noConflict = function () {
        return a.fn.button = c, this
    }, a(document).on("click.button.data-api", "[data-toggle^=button]", function (b) {
        var c = a(b.target);
        c.hasClass("btn") || (c = c.closest(".btn")), c.button("toggle")
    })
}(window.jQuery), ! function (a) {
    var b = function (b, c) {
        this.$element = a(b), this.options = a.extend({}, a.fn.collapse.defaults, c), this.options.parent && (this.$parent = a(this.options.parent)), this.options.toggle && this.toggle()
    };
    b.prototype = {
        constructor: b,
        dimension: function () {
            var a = this.$element.hasClass("width");
            return a ? "width" : "height"
        },
        show: function () {
            var b, c, d, e;
            if (!this.transitioning && !this.$element.hasClass("in")) {
                if (b = this.dimension(), c = a.camelCase(["scroll", b].join("-")), d = this.$parent && this.$parent.find("> .accordion-group > .in"), d && d.length) {
                    if (e = d.data("collapse"), e && e.transitioning) return;
                    d.collapse("hide"), e || d.data("collapse", null)
                }
                this.$element[b](0), this.transition("addClass", a.Event("show"), "shown"), a.support.transition && this.$element[b](this.$element[0][c])
            }
        },
        hide: function () {
            var b;
            !this.transitioning && this.$element.hasClass("in") && (b = this.dimension(), this.reset(this.$element[b]()), this.transition("removeClass", a.Event("hide"), "hidden"), this.$element[b](0))
        },
        reset: function (a) {
            var b = this.dimension();
            return this.$element.removeClass("collapse")[b](a || "auto")[0].offsetWidth, this.$element[null !== a ? "addClass" : "removeClass"]("collapse"), this
        },
        transition: function (b, c, d) {
            var e = this,
                f = function () {
                    "show" == c.type && e.reset(), e.transitioning = 0, e.$element.trigger(d)
                };
            this.$element.trigger(c), c.isDefaultPrevented() || (this.transitioning = 1, this.$element[b]("in"), a.support.transition && this.$element.hasClass("collapse") ? this.$element.one(a.support.transition.end, f) : f())
        },
        toggle: function () {
            this[this.$element.hasClass("in") ? "hide" : "show"]()
        }
    };
    var c = a.fn.collapse;
    a.fn.collapse = function (c) {
        return this.each(function () {
            var d = a(this),
                e = d.data("collapse"),
                f = a.extend({}, a.fn.collapse.defaults, d.data(), "object" == typeof c && c);
            e || d.data("collapse", e = new b(this, f)), "string" == typeof c && e[c]()
        })
    }, a.fn.collapse.defaults = {
        toggle: !0
    }, a.fn.collapse.Constructor = b, a.fn.collapse.noConflict = function () {
        return a.fn.collapse = c, this
    }, a(document).on("click.collapse.data-api", "[data-toggle=collapse]", function (b) {
        var d, c = a(this),
            e = c.attr("data-target") || b.preventDefault() || (d = c.attr("href")) && d.replace(/.*(?=#[^\s]+$)/, ""),
            f = a(e).data("collapse") ? "toggle" : c.data();
        c[a(e).hasClass("in") ? "addClass" : "removeClass"]("collapsed"), a(e).collapse(f)
    })
}(window.jQuery), ! function (a) {
    var b = function (b, c) {
        this.$element = a(b), this.$indicators = this.$element.find(".carousel-indicators"), this.options = c, "hover" == this.options.pause && this.$element.on("mouseenter", a.proxy(this.pause, this)).on("mouseleave", a.proxy(this.cycle, this))
    };
    b.prototype = {
        cycle: function (b) {
            return b || (this.paused = !1), this.interval && clearInterval(this.interval), this.options.interval && !this.paused && (this.interval = setInterval(a.proxy(this.next, this), this.options.interval)), this
        },
        getActiveIndex: function () {
            return this.$active = this.$element.find(".item.active"), this.$items = this.$active.parent().children(), this.$items.index(this.$active)
        },
        to: function (b) {
            var c = this.getActiveIndex(),
                d = this;
            if (!(b > this.$items.length - 1 || 0 > b)) return this.sliding ? this.$element.one("slid", function () {
                d.to(b)
            }) : c == b ? this.pause().cycle() : this.slide(b > c ? "next" : "prev", a(this.$items[b]))
        },
        pause: function (b) {
            return b || (this.paused = !0), this.$element.find(".next, .prev").length && a.support.transition.end && (this.$element.trigger(a.support.transition.end), this.cycle()), clearInterval(this.interval), this.interval = null, this
        },
        next: function () {
            return this.sliding ? void 0 : this.slide("next")
        },
        prev: function () {
            return this.sliding ? void 0 : this.slide("prev")
        },
        slide: function (b, c) {
            var j, d = this.$element.find(".item.active"),
                e = c || d[b](),
                f = this.interval,
                g = "next" == b ? "left" : "right",
                h = "next" == b ? "first" : "last",
                i = this;
            if (this.sliding = !0, f && this.pause(), e = e.length ? e : this.$element.find(".item")[h](), j = a.Event("slide", {
                relatedTarget: e[0],
                direction: g
            }), !e.hasClass("active")) {
                if (this.$indicators.length && (this.$indicators.find(".active").removeClass("active"), this.$element.one("slid", function () {
                    var b = a(i.$indicators.children()[i.getActiveIndex()]);
                    b && b.addClass("active")
                })), a.support.transition && this.$element.hasClass("slide")) {
                    if (this.$element.trigger(j), j.isDefaultPrevented()) return;
                    e.addClass(b), e[0].offsetWidth, d.addClass(g), e.addClass(g), this.$element.one(a.support.transition.end, function () {
                        e.removeClass([b, g].join(" ")).addClass("active"), d.removeClass(["active", g].join(" ")), i.sliding = !1, setTimeout(function () {
                            i.$element.trigger("slid")
                        }, 0)
                    })
                } else {
                    if (this.$element.trigger(j), j.isDefaultPrevented()) return;
                    d.removeClass("active"), e.addClass("active"), this.sliding = !1, this.$element.trigger("slid")
                }
                return f && this.cycle(), this
            }
        }
    };
    var c = a.fn.carousel;
    a.fn.carousel = function (c) {
        return this.each(function () {
            var d = a(this),
                e = d.data("carousel"),
                f = a.extend({}, a.fn.carousel.defaults, "object" == typeof c && c),
                g = "string" == typeof c ? c : f.slide;
            e || d.data("carousel", e = new b(this, f)), "number" == typeof c ? e.to(c) : g ? e[g]() : f.interval && e.pause().cycle()
        })
    }, a.fn.carousel.defaults = {
        interval: 5e3,
        pause: "hover"
    }, a.fn.carousel.Constructor = b, a.fn.carousel.noConflict = function () {
        return a.fn.carousel = c, this
    }, a(document).on("click.carousel.data-api", "[data-slide], [data-slide-to]", function (b) {
        var d, g, c = a(this),
            e = a(c.attr("data-target") || (d = c.attr("href")) && d.replace(/.*(?=#[^\s]+$)/, "")),
            f = a.extend({}, e.data(), c.data());
        e.carousel(f), (g = c.attr("data-slide-to")) && e.data("carousel").pause().to(g).cycle(), b.preventDefault()
    })
}(window.jQuery), ! function (a) {
    var b = function (b, c) {
        this.$element = a(b), this.options = a.extend({}, a.fn.typeahead.defaults, c), this.matcher = this.options.matcher || this.matcher, this.sorter = this.options.sorter || this.sorter, this.highlighter = this.options.highlighter || this.highlighter, this.updater = this.options.updater || this.updater, this.source = this.options.source, this.$menu = a(this.options.menu), this.shown = !1, this.listen()
    };
    b.prototype = {
        constructor: b,
        select: function () {
            var a = this.$menu.find(".active").attr("data-value");
            return this.$element.val(this.updater(a)).change(), this.hide()
        },
        updater: function (a) {
            return a
        },
        show: function () {
            var b = a.extend({}, this.$element.position(), {
                height: this.$element[0].offsetHeight
            });
            return this.$menu.insertAfter(this.$element).css({
                top: b.top + b.height,
                left: b.left
            }).show(), this.shown = !0, this
        },
        hide: function () {
            return this.$menu.hide(), this.shown = !1, this
        },
        lookup: function () {
            var c;
            return this.query = this.$element.val(), !this.query || this.query.length < this.options.minLength ? this.shown ? this.hide() : this : (c = a.isFunction(this.source) ? this.source(this.query, a.proxy(this.process, this)) : this.source, c ? this.process(c) : this)
        },
        process: function (b) {
            var c = this;
            return b = a.grep(b, function (a) {
                return c.matcher(a)
            }), b = this.sorter(b), b.length ? this.render(b.slice(0, this.options.items)).show() : this.shown ? this.hide() : this
        },
        matcher: function (a) {
            return~ a.toLowerCase().indexOf(this.query.toLowerCase())
        },
        sorter: function (a) {
            for (var e, b = [], c = [], d = []; e = a.shift();) e.toLowerCase().indexOf(this.query.toLowerCase()) ? ~e.indexOf(this.query) ? c.push(e) : d.push(e) : b.push(e);
            return b.concat(c, d)
        },
        highlighter: function (a) {
            var b = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
            return a.replace(new RegExp("(" + b + ")", "ig"), function (a, b) {
                return "<strong>" + b + "</strong>"
            })
        },
        render: function (b) {
            var c = this;
            return b = a(b).map(function (b, d) {
                return b = a(c.options.item).attr("data-value", d), b.find("a").html(c.highlighter(d)), b[0]
            }), b.first().addClass("active"), this.$menu.html(b), this
        },
        next: function () {
            var c = this.$menu.find(".active").removeClass("active"),
                d = c.next();
            d.length || (d = a(this.$menu.find("li")[0])), d.addClass("active")
        },
        prev: function () {
            var b = this.$menu.find(".active").removeClass("active"),
                c = b.prev();
            c.length || (c = this.$menu.find("li").last()), c.addClass("active")
        },
        listen: function () {
            this.$element.on("focus", a.proxy(this.focus, this)).on("blur", a.proxy(this.blur, this)).on("keypress", a.proxy(this.keypress, this)).on("keyup", a.proxy(this.keyup, this)), this.eventSupported("keydown") && this.$element.on("keydown", a.proxy(this.keydown, this)), this.$menu.on("click", a.proxy(this.click, this)).on("mouseenter", "li", a.proxy(this.mouseenter, this)).on("mouseleave", "li", a.proxy(this.mouseleave, this))
        },
        eventSupported: function (a) {
            var b = a in this.$element;
            return b || (this.$element.setAttribute(a, "return;"), b = "function" == typeof this.$element[a]), b
        },
        move: function (a) {
            if (this.shown) {
                switch (a.keyCode) {
                case 9:
                case 13:
                case 27:
                    a.preventDefault();
                    break;
                case 38:
                    a.preventDefault(), this.prev();
                    break;
                case 40:
                    a.preventDefault(), this.next()
                }
                a.stopPropagation()
            }
        },
        keydown: function (b) {
            this.suppressKeyPressRepeat = ~a.inArray(b.keyCode, [40, 38, 9, 13, 27]), this.move(b)
        },
        keypress: function (a) {
            this.suppressKeyPressRepeat || this.move(a)
        },
        keyup: function (a) {
            switch (a.keyCode) {
            case 40:
            case 38:
            case 16:
            case 17:
            case 18:
                break;
            case 9:
            case 13:
                if (!this.shown) return;
                this.select();
                break;
            case 27:
                if (!this.shown) return;
                this.hide();
                break;
            default:
                this.lookup()
            }
            a.stopPropagation(), a.preventDefault()
        },
        focus: function () {
            this.focused = !0
        },
        blur: function () {
            this.focused = !1, !this.mousedover && this.shown && this.hide()
        },
        click: function (a) {
            a.stopPropagation(), a.preventDefault(), this.select(), this.$element.focus()
        },
        mouseenter: function (b) {
            this.mousedover = !0, this.$menu.find(".active").removeClass("active"), a(b.currentTarget).addClass("active")
        },
        mouseleave: function () {
            this.mousedover = !1, !this.focused && this.shown && this.hide()
        }
    };
    var c = a.fn.typeahead;
    a.fn.typeahead = function (c) {
        return this.each(function () {
            var d = a(this),
                e = d.data("typeahead"),
                f = "object" == typeof c && c;
            e || d.data("typeahead", e = new b(this, f)), "string" == typeof c && e[c]()
        })
    }, a.fn.typeahead.defaults = {
        source: [],
        items: 8,
        menu: '<ul class="typeahead dropdown-menu"></ul>',
        item: '<li><a href="#"></a></li>',
        minLength: 1
    }, a.fn.typeahead.Constructor = b, a.fn.typeahead.noConflict = function () {
        return a.fn.typeahead = c, this
    }, a(document).on("focus.typeahead.data-api", '[data-provide="typeahead"]', function () {
        var c = a(this);
        c.data("typeahead") || c.typeahead(c.data())
    })
}(window.jQuery), ! function (e) {
    "use strict";
    var t = function (t, n) {
        this.options = n, this.$element = e(t).delegate('[data-dismiss="lightbox"]', "click.dismiss.lightbox", e.proxy(this.hide, this)), this.options.remote && this.$element.find(".lightbox-body").load(this.options.remote)
    };
    t.prototype = e.extend({}, e.fn.modal.Constructor.prototype), t.prototype.constructor = t, t.prototype.enforceFocus = function () {
        var t = this;
        e(document).on("focusin.lightbox", function (e) {
            t.$element[0] !== e.target && !t.$element.has(e.target).length && t.$element.focus()
        })
    }, t.prototype.show = function () {
        var t = this,
            n = e.Event("show");
        t.$element.find(".hide-lightbox").on("click", function () {
            t.hide()
        }), this.$element.trigger(n), this.isShown || n.isDefaultPrevented() || (this.isShown = !0, this.escape(), this.preloadSize(function () {
            t.backdrop(function () {
                var n = e.support.transition && t.$element.hasClass("fade");
                t.$element.parent().length || t.$element.appendTo(document.body), t.$element.show(), n && t.$element[0].offsetWidth, t.$element.addClass("in").attr("aria-hidden", !1), t.enforceFocus(), n ? t.$element.one(e.support.transition.end, function () {
                    t.$element.focus().trigger("shown")
                }) : t.$element.focus().trigger("shown")
            })
        }))
    }, t.prototype.hide = function (t) {
        t && t.preventDefault(), t = e.Event("hide"), this.$element.trigger(t), this.isShown && !t.isDefaultPrevented() && (this.isShown = !1, this.escape(), e(document).off("focusin.lightbox"), this.$element.removeClass("in").attr("aria-hidden", !0), e.support.transition && this.$element.hasClass("fade") ? this.hideWithTransition() : this.hideModal())
    }, t.prototype.escape = function () {
        var e = this;
        this.isShown && this.options.keyboard ? this.$element.on("keyup.dismiss.lightbox", function (t) {
            27 == t.which && e.hide()
        }) : this.isShown || this.$element.off("keyup.dismiss.lightbox")
    }, t.prototype.preloadSize = function (t) {
        var n = e.Callbacks();
        t && n.add(t);
        var i, s, o, u, a, f, l, c, h, p, r = this;
        i = e(window).height(), s = e(window).width(), o = parseInt(r.$element.find(".lightbox-content").css("padding-top"), 10), u = parseInt(r.$element.find(".lightbox-content").css("padding-bottom"), 10), a = parseInt(r.$element.find(".lightbox-content").css("padding-left"), 10), f = parseInt(r.$element.find(".lightbox-content").css("padding-right"), 10), l = r.$element.find(".lightbox-content").find("img:first"), c = new Image, c.onload = function () {
            c.width + a + f >= s && (h = c.width, p = c.height, c.width = s - a - f, c.height = p / h * c.width), c.height + o + u >= i && (h = c.width, p = c.height, c.height = i - o - u, c.width = h / p * c.height), r.$element.css({
                "z-index": "9999",
                position: "fixed",
                width: c.width + a + f,
                height: c.height + o + u,
                top: i / 2 - (c.height + o + u) / 2,
                left: "50%",
                "margin-left": -1 * (c.width + a + f) / 2
            }), r.$element.find(".lightbox-content").css({
                width: c.width,
                height: c.height
            }), n.fire()
        }, c.src = l.attr("src")
    };
    var n = e.fn.lightbox;
    e.fn.lightbox = function (n) {
        return this.each(function () {
            var r = e(this),
                i = r.data("lightbox"),
                s = e.extend({}, e.fn.lightbox.defaults, r.data(), "object" == typeof n && n);
            i || r.data("lightbox", i = new t(this, s)), "string" == typeof n ? i[n]() : s.show && i.show()
        })
    }, e.fn.lightbox.defaults = {
        backdrop: !0,
        keyboard: !0,
        show: !0
    }, e.fn.lightbox.Constructor = t, e.fn.lightbox.noConflict = function () {
        return e.fn.lightbox = n, this
    }, e(document).on("click.lightbox.data-api", '[data-toggle*="lightbox"]', function (t) {
        var n = e(this),
            r = n.attr("href"),
            i = e(n.attr("data-target") || r && r.replace(/.*(?=#[^\s]+$)/, "")),
            s = i.data("lightbox") ? "toggle" : e.extend({
                remote: !/#/.test(r) && r
            }, i.data(), n.data());
        t.preventDefault(), i.lightbox(s).one("hide", function () {
            n.focus()
        })
    })
}(window.jQuery),
function () {
    var n = this,
        t = n._,
        r = {},
        e = Array.prototype,
        u = Object.prototype,
        i = Function.prototype,
        a = e.push,
        o = e.slice,
        c = e.concat,
        l = u.toString,
        f = u.hasOwnProperty,
        s = e.forEach,
        p = e.map,
        h = e.reduce,
        v = e.reduceRight,
        g = e.filter,
        d = e.every,
        m = e.some,
        y = e.indexOf,
        b = e.lastIndexOf,
        x = Array.isArray,
        w = Object.keys,
        _ = i.bind,
        j = function (n) {
            return n instanceof j ? n : this instanceof j ? (this._wrapped = n, void 0) : new j(n)
        };
    "undefined" != typeof exports ? ("undefined" != typeof module && module.exports && (exports = module.exports = j), exports._ = j) : n._ = j, j.VERSION = "1.5.2";
    var A = j.each = j.forEach = function (n, t, e) {
        if (null != n)
            if (s && n.forEach === s) n.forEach(t, e);
            else if (n.length === +n.length) {
            for (var u = 0, i = n.length; i > u; u++)
                if (t.call(e, n[u], u, n) === r) return
        } else
            for (var a = j.keys(n), u = 0, i = a.length; i > u; u++)
                if (t.call(e, n[a[u]], a[u], n) === r) return
    };
    j.map = j.collect = function (n, t, r) {
        var e = [];
        return null == n ? e : p && n.map === p ? n.map(t, r) : (A(n, function (n, u, i) {
            e.push(t.call(r, n, u, i))
        }), e)
    };
    var E = "Reduce of empty array with no initial value";
    j.reduce = j.foldl = j.inject = function (n, t, r, e) {
        var u = arguments.length > 2;
        if (null == n && (n = []), h && n.reduce === h) return e && (t = j.bind(t, e)), u ? n.reduce(t, r) : n.reduce(t);
        if (A(n, function (n, i, a) {
            u ? r = t.call(e, r, n, i, a) : (r = n, u = !0)
        }), !u) throw new TypeError(E);
        return r
    }, j.reduceRight = j.foldr = function (n, t, r, e) {
        var u = arguments.length > 2;
        if (null == n && (n = []), v && n.reduceRight === v) return e && (t = j.bind(t, e)), u ? n.reduceRight(t, r) : n.reduceRight(t);
        var i = n.length;
        if (i !== +i) {
            var a = j.keys(n);
            i = a.length
        }
        if (A(n, function (o, c, l) {
            c = a ? a[--i] : --i, u ? r = t.call(e, r, n[c], c, l) : (r = n[c], u = !0)
        }), !u) throw new TypeError(E);
        return r
    }, j.find = j.detect = function (n, t, r) {
        var e;
        return O(n, function (n, u, i) {
            return t.call(r, n, u, i) ? (e = n, !0) : void 0
        }), e
    }, j.filter = j.select = function (n, t, r) {
        var e = [];
        return null == n ? e : g && n.filter === g ? n.filter(t, r) : (A(n, function (n, u, i) {
            t.call(r, n, u, i) && e.push(n)
        }), e)
    }, j.reject = function (n, t, r) {
        return j.filter(n, function (n, e, u) {
            return !t.call(r, n, e, u)
        }, r)
    }, j.every = j.all = function (n, t, e) {
        t || (t = j.identity);
        var u = !0;
        return null == n ? u : d && n.every === d ? n.every(t, e) : (A(n, function (n, i, a) {
            return (u = u && t.call(e, n, i, a)) ? void 0 : r
        }), !!u)
    };
    var O = j.some = j.any = function (n, t, e) {
        t || (t = j.identity);
        var u = !1;
        return null == n ? u : m && n.some === m ? n.some(t, e) : (A(n, function (n, i, a) {
            return u || (u = t.call(e, n, i, a)) ? r : void 0
        }), !!u)
    };
    j.contains = j.include = function (n, t) {
        return null == n ? !1 : y && n.indexOf === y ? -1 != n.indexOf(t) : O(n, function (n) {
            return n === t
        })
    }, j.invoke = function (n, t) {
        var r = o.call(arguments, 2),
            e = j.isFunction(t);
        return j.map(n, function (n) {
            return (e ? t : n[t]).apply(n, r)
        })
    }, j.pluck = function (n, t) {
        return j.map(n, function (n) {
            return n[t]
        })
    }, j.where = function (n, t, r) {
        return j.isEmpty(t) ? r ? void 0 : [] : j[r ? "find" : "filter"](n, function (n) {
            for (var r in t)
                if (t[r] !== n[r]) return !1;
            return !0
        })
    }, j.findWhere = function (n, t) {
        return j.where(n, t, !0)
    }, j.max = function (n, t, r) {
        if (!t && j.isArray(n) && n[0] === +n[0] && n.length < 65535) return Math.max.apply(Math, n);
        if (!t && j.isEmpty(n)) return -1 / 0;
        var e = {
            computed: -1 / 0,
            value: -1 / 0
        };
        return A(n, function (n, u, i) {
            var a = t ? t.call(r, n, u, i) : n;
            a > e.computed && (e = {
                value: n,
                computed: a
            })
        }), e.value
    }, j.min = function (n, t, r) {
        if (!t && j.isArray(n) && n[0] === +n[0] && n.length < 65535) return Math.min.apply(Math, n);
        if (!t && j.isEmpty(n)) return 1 / 0;
        var e = {
            computed: 1 / 0,
            value: 1 / 0
        };
        return A(n, function (n, u, i) {
            var a = t ? t.call(r, n, u, i) : n;
            a < e.computed && (e = {
                value: n,
                computed: a
            })
        }), e.value
    }, j.shuffle = function (n) {
        var t, r = 0,
            e = [];
        return A(n, function (n) {
            t = j.random(r++), e[r - 1] = e[t], e[t] = n
        }), e
    }, j.sample = function (n, t, r) {
        return arguments.length < 2 || r ? n[j.random(n.length - 1)] : j.shuffle(n).slice(0, Math.max(0, t))
    };
    var k = function (n) {
        return j.isFunction(n) ? n : function (t) {
            return t[n]
        }
    };
    j.sortBy = function (n, t, r) {
        var e = k(t);
        return j.pluck(j.map(n, function (n, t, u) {
            return {
                value: n,
                index: t,
                criteria: e.call(r, n, t, u)
            }
        }).sort(function (n, t) {
            var r = n.criteria,
                e = t.criteria;
            if (r !== e) {
                if (r > e || void 0 === r) return 1;
                if (e > r || void 0 === e) return -1
            }
            return n.index - t.index
        }), "value")
    };
    var F = function (n) {
        return function (t, r, e) {
            var u = {},
                i = null == r ? j.identity : k(r);
            return A(t, function (r, a) {
                var o = i.call(e, r, a, t);
                n(u, o, r)
            }), u
        }
    };
    j.groupBy = F(function (n, t, r) {
        (j.has(n, t) ? n[t] : n[t] = []).push(r)
    }), j.indexBy = F(function (n, t, r) {
        n[t] = r
    }), j.countBy = F(function (n, t) {
        j.has(n, t) ? n[t]++ : n[t] = 1
    }), j.sortedIndex = function (n, t, r, e) {
        r = null == r ? j.identity : k(r);
        for (var u = r.call(e, t), i = 0, a = n.length; a > i;) {
            var o = i + a >>> 1;
            r.call(e, n[o]) < u ? i = o + 1 : a = o
        }
        return i
    }, j.toArray = function (n) {
        return n ? j.isArray(n) ? o.call(n) : n.length === +n.length ? j.map(n, j.identity) : j.values(n) : []
    }, j.size = function (n) {
        return null == n ? 0 : n.length === +n.length ? n.length : j.keys(n).length
    }, j.first = j.head = j.take = function (n, t, r) {
        return null == n ? void 0 : null == t || r ? n[0] : o.call(n, 0, t)
    }, j.initial = function (n, t, r) {
        return o.call(n, 0, n.length - (null == t || r ? 1 : t))
    }, j.last = function (n, t, r) {
        return null == n ? void 0 : null == t || r ? n[n.length - 1] : o.call(n, Math.max(n.length - t, 0))
    }, j.rest = j.tail = j.drop = function (n, t, r) {
        return o.call(n, null == t || r ? 1 : t)
    }, j.compact = function (n) {
        return j.filter(n, j.identity)
    };
    var M = function (n, t, r) {
        return t && j.every(n, j.isArray) ? c.apply(r, n) : (A(n, function (n) {
            j.isArray(n) || j.isArguments(n) ? t ? a.apply(r, n) : M(n, t, r) : r.push(n)
        }), r)
    };
    j.flatten = function (n, t) {
        return M(n, t, [])
    }, j.without = function (n) {
        return j.difference(n, o.call(arguments, 1))
    }, j.uniq = j.unique = function (n, t, r, e) {
        j.isFunction(t) && (e = r, r = t, t = !1);
        var u = r ? j.map(n, r, e) : n,
            i = [],
            a = [];
        return A(u, function (r, e) {
            (t ? e && a[a.length - 1] === r : j.contains(a, r)) || (a.push(r), i.push(n[e]))
        }), i
    }, j.union = function () {
        return j.uniq(j.flatten(arguments, !0))
    }, j.intersection = function (n) {
        var t = o.call(arguments, 1);
        return j.filter(j.uniq(n), function (n) {
            return j.every(t, function (t) {
                return j.indexOf(t, n) >= 0
            })
        })
    }, j.difference = function (n) {
        var t = c.apply(e, o.call(arguments, 1));
        return j.filter(n, function (n) {
            return !j.contains(t, n)
        })
    }, j.zip = function () {
        for (var n = j.max(j.pluck(arguments, "length").concat(0)), t = new Array(n), r = 0; n > r; r++) t[r] = j.pluck(arguments, "" + r);
        return t
    }, j.object = function (n, t) {
        if (null == n) return {};
        for (var r = {}, e = 0, u = n.length; u > e; e++) t ? r[n[e]] = t[e] : r[n[e][0]] = n[e][1];
        return r
    }, j.indexOf = function (n, t, r) {
        if (null == n) return -1;
        var e = 0,
            u = n.length;
        if (r) {
            if ("number" != typeof r) return e = j.sortedIndex(n, t), n[e] === t ? e : -1;
            e = 0 > r ? Math.max(0, u + r) : r
        }
        if (y && n.indexOf === y) return n.indexOf(t, r);
        for (; u > e; e++)
            if (n[e] === t) return e;
        return -1
    }, j.lastIndexOf = function (n, t, r) {
        if (null == n) return -1;
        var e = null != r;
        if (b && n.lastIndexOf === b) return e ? n.lastIndexOf(t, r) : n.lastIndexOf(t);
        for (var u = e ? r : n.length; u--;)
            if (n[u] === t) return u;
        return -1
    }, j.range = function (n, t, r) {
        arguments.length <= 1 && (t = n || 0, n = 0), r = arguments[2] || 1;
        for (var e = Math.max(Math.ceil((t - n) / r), 0), u = 0, i = new Array(e); e > u;) i[u++] = n, n += r;
        return i
    };
    var R = function () {};
    j.bind = function (n, t) {
        var r, e;
        if (_ && n.bind === _) return _.apply(n, o.call(arguments, 1));
        if (!j.isFunction(n)) throw new TypeError;
        return r = o.call(arguments, 2), e = function () {
            if (!(this instanceof e)) return n.apply(t, r.concat(o.call(arguments)));
            R.prototype = n.prototype;
            var u = new R;
            R.prototype = null;
            var i = n.apply(u, r.concat(o.call(arguments)));
            return Object(i) === i ? i : u
        }
    }, j.partial = function (n) {
        var t = o.call(arguments, 1);
        return function () {
            return n.apply(this, t.concat(o.call(arguments)))
        }
    }, j.bindAll = function (n) {
        var t = o.call(arguments, 1);
        if (0 === t.length) throw new Error("bindAll must be passed function names");
        return A(t, function (t) {
            n[t] = j.bind(n[t], n)
        }), n
    }, j.memoize = function (n, t) {
        var r = {};
        return t || (t = j.identity),
            function () {
                var e = t.apply(this, arguments);
                return j.has(r, e) ? r[e] : r[e] = n.apply(this, arguments)
            }
    }, j.delay = function (n, t) {
        var r = o.call(arguments, 2);
        return setTimeout(function () {
            return n.apply(null, r)
        }, t)
    }, j.defer = function (n) {
        return j.delay.apply(j, [n, 1].concat(o.call(arguments, 1)))
    }, j.throttle = function (n, t, r) {
        var e, u, i, a = null,
            o = 0;
        r || (r = {});
        var c = function () {
            o = r.leading === !1 ? 0 : new Date, a = null, i = n.apply(e, u)
        };
        return function () {
            var l = new Date;
            o || r.leading !== !1 || (o = l);
            var f = t - (l - o);
            return e = this, u = arguments, 0 >= f ? (clearTimeout(a), a = null, o = l, i = n.apply(e, u)) : a || r.trailing === !1 || (a = setTimeout(c, f)), i
        }
    }, j.debounce = function (n, t, r) {
        var e, u, i, a, o;
        return function () {
            i = this, u = arguments, a = new Date;
            var c = function () {
                    var l = new Date - a;
                    t > l ? e = setTimeout(c, t - l) : (e = null, r || (o = n.apply(i, u)))
                },
                l = r && !e;
            return e || (e = setTimeout(c, t)), l && (o = n.apply(i, u)), o
        }
    }, j.once = function (n) {
        var t, r = !1;
        return function () {
            return r ? t : (r = !0, t = n.apply(this, arguments), n = null, t)
        }
    }, j.wrap = function (n, t) {
        return function () {
            var r = [n];
            return a.apply(r, arguments), t.apply(this, r)
        }
    }, j.compose = function () {
        var n = arguments;
        return function () {
            for (var t = arguments, r = n.length - 1; r >= 0; r--) t = [n[r].apply(this, t)];
            return t[0]
        }
    }, j.after = function (n, t) {
        return function () {
            return --n < 1 ? t.apply(this, arguments) : void 0
        }
    }, j.keys = w || function (n) {
        if (n !== Object(n)) throw new TypeError("Invalid object");
        var t = [];
        for (var r in n) j.has(n, r) && t.push(r);
        return t
    }, j.values = function (n) {
        for (var t = j.keys(n), r = t.length, e = new Array(r), u = 0; r > u; u++) e[u] = n[t[u]];
        return e
    }, j.pairs = function (n) {
        for (var t = j.keys(n), r = t.length, e = new Array(r), u = 0; r > u; u++) e[u] = [t[u], n[t[u]]];
        return e
    }, j.invert = function (n) {
        for (var t = {}, r = j.keys(n), e = 0, u = r.length; u > e; e++) t[n[r[e]]] = r[e];
        return t
    }, j.functions = j.methods = function (n) {
        var t = [];
        for (var r in n) j.isFunction(n[r]) && t.push(r);
        return t.sort()
    }, j.extend = function (n) {
        return A(o.call(arguments, 1), function (t) {
            if (t)
                for (var r in t) n[r] = t[r]
        }), n
    }, j.pick = function (n) {
        var t = {},
            r = c.apply(e, o.call(arguments, 1));
        return A(r, function (r) {
            r in n && (t[r] = n[r])
        }), t
    }, j.omit = function (n) {
        var t = {},
            r = c.apply(e, o.call(arguments, 1));
        for (var u in n) j.contains(r, u) || (t[u] = n[u]);
        return t
    }, j.defaults = function (n) {
        return A(o.call(arguments, 1), function (t) {
            if (t)
                for (var r in t) void 0 === n[r] && (n[r] = t[r])
        }), n
    }, j.clone = function (n) {
        return j.isObject(n) ? j.isArray(n) ? n.slice() : j.extend({}, n) : n
    }, j.tap = function (n, t) {
        return t(n), n
    };
    var S = function (n, t, r, e) {
        if (n === t) return 0 !== n || 1 / n == 1 / t;
        if (null == n || null == t) return n === t;
        n instanceof j && (n = n._wrapped), t instanceof j && (t = t._wrapped);
        var u = l.call(n);
        if (u != l.call(t)) return !1;
        switch (u) {
        case "[object String]":
            return n == String(t);
        case "[object Number]":
            return n != +n ? t != +t : 0 == n ? 1 / n == 1 / t : n == +t;
        case "[object Date]":
        case "[object Boolean]":
            return +n == +t;
        case "[object RegExp]":
            return n.source == t.source && n.global == t.global && n.multiline == t.multiline && n.ignoreCase == t.ignoreCase
        }
        if ("object" != typeof n || "object" != typeof t) return !1;
        for (var i = r.length; i--;)
            if (r[i] == n) return e[i] == t;
        var a = n.constructor,
            o = t.constructor;
        if (a !== o && !(j.isFunction(a) && a instanceof a && j.isFunction(o) && o instanceof o)) return !1;
        r.push(n), e.push(t);
        var c = 0,
            f = !0;
        if ("[object Array]" == u) {
            if (c = n.length, f = c == t.length)
                for (; c-- && (f = S(n[c], t[c], r, e)););
        } else {
            for (var s in n)
                if (j.has(n, s) && (c++, !(f = j.has(t, s) && S(n[s], t[s], r, e)))) break;
            if (f) {
                for (s in t)
                    if (j.has(t, s) && !c--) break;
                f = !c
            }
        }
        return r.pop(), e.pop(), f
    };
    j.isEqual = function (n, t) {
        return S(n, t, [], [])
    }, j.isEmpty = function (n) {
        if (null == n) return !0;
        if (j.isArray(n) || j.isString(n)) return 0 === n.length;
        for (var t in n)
            if (j.has(n, t)) return !1;
        return !0
    }, j.isElement = function (n) {
        return !(!n || 1 !== n.nodeType)
    }, j.isArray = x || function (n) {
        return "[object Array]" == l.call(n)
    }, j.isObject = function (n) {
        return n === Object(n)
    }, A(["Arguments", "Function", "String", "Number", "Date", "RegExp"], function (n) {
        j["is" + n] = function (t) {
            return l.call(t) == "[object " + n + "]"
        }
    }), j.isArguments(arguments) || (j.isArguments = function (n) {
        return !(!n || !j.has(n, "callee"))
    }), "function" != typeof / . / && (j.isFunction = function (n) {
        return "function" == typeof n
    }), j.isFinite = function (n) {
        return isFinite(n) && !isNaN(parseFloat(n))
    }, j.isNaN = function (n) {
        return j.isNumber(n) && n != +n
    }, j.isBoolean = function (n) {
        return n === !0 || n === !1 || "[object Boolean]" == l.call(n)
    }, j.isNull = function (n) {
        return null === n
    }, j.isUndefined = function (n) {
        return void 0 === n
    }, j.has = function (n, t) {
        return f.call(n, t)
    }, j.noConflict = function () {
        return n._ = t, this
    }, j.identity = function (n) {
        return n
    }, j.times = function (n, t, r) {
        for (var e = Array(Math.max(0, n)), u = 0; n > u; u++) e[u] = t.call(r, u);
        return e
    }, j.random = function (n, t) {
        return null == t && (t = n, n = 0), n + Math.floor(Math.random() * (t - n + 1))
    };
    var I = {
        escape: {
            "&": "&amp;",
            "<": "&lt;",
            ">": "&gt;",
            '"': "&quot;",
            "'": "&#x27;"
        }
    };
    I.unescape = j.invert(I.escape);
    var T = {
        escape: new RegExp("[" + j.keys(I.escape).join("") + "]", "g"),
        unescape: new RegExp("(" + j.keys(I.unescape).join("|") + ")", "g")
    };
    j.each(["escape", "unescape"], function (n) {
        j[n] = function (t) {
            return null == t ? "" : ("" + t).replace(T[n], function (t) {
                return I[n][t]
            })
        }
    }), j.result = function (n, t) {
        if (null == n) return void 0;
        var r = n[t];
        return j.isFunction(r) ? r.call(n) : r
    }, j.mixin = function (n) {
        A(j.functions(n), function (t) {
            var r = j[t] = n[t];
            j.prototype[t] = function () {
                var n = [this._wrapped];
                return a.apply(n, arguments), z.call(this, r.apply(j, n))
            }
        })
    };
    var N = 0;
    j.uniqueId = function (n) {
        var t = ++N + "";
        return n ? n + t : t
    }, j.templateSettings = {
        evaluate: /<%([\s\S]+?)%>/g,
        interpolate: /<%=([\s\S]+?)%>/g,
        escape: /<%-([\s\S]+?)%>/g
    };
    var q = /(.)^/,
        B = {
            "'": "'",
            "\\": "\\",
            "\r": "r",
            "\n": "n",
            "	": "t",
            "\u2028": "u2028",
            "\u2029": "u2029"
        },
        D = /\\|'|\r|\n|\t|\u2028|\u2029/g;
    j.template = function (n, t, r) {
        var e;
        r = j.defaults({}, r, j.templateSettings);
        var u = new RegExp([(r.escape || q).source, (r.interpolate || q).source, (r.evaluate || q).source].join("|") + "|$", "g"),
            i = 0,
            a = "__p+='";
        n.replace(u, function (t, r, e, u, o) {
            return a += n.slice(i, o).replace(D, function (n) {
                return "\\" + B[n]
            }), r && (a += "'+\n((__t=(" + r + "))==null?'':_.escape(__t))+\n'"), e && (a += "'+\n((__t=(" + e + "))==null?'':__t)+\n'"), u && (a += "';\n" + u + "\n__p+='"), i = o + t.length, t
        }), a += "';\n", r.variable || (a = "with(obj||{}){\n" + a + "}\n"), a = "var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n" + a + "return __p;\n";
        try {
            e = new Function(r.variable || "obj", "_", a)
        } catch (o) {
            throw o.source = a, o
        }
        if (t) return e(t, j);
        var c = function (n) {
            return e.call(this, n, j)
        };
        return c.source = "function(" + (r.variable || "obj") + "){\n" + a + "}", c
    }, j.chain = function (n) {
        return j(n).chain()
    };
    var z = function (n) {
        return this._chain ? j(n).chain() : n
    };
    j.mixin(j), A(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (n) {
        var t = e[n];
        j.prototype[n] = function () {
            var r = this._wrapped;
            return t.apply(r, arguments), "shift" != n && "splice" != n || 0 !== r.length || delete r[0], z.call(this, r)
        }
    }), A(["concat", "join", "slice"], function (n) {
        var t = e[n];
        j.prototype[n] = function () {
            return z.call(this, t.apply(this._wrapped, arguments))
        }
    }), j.extend(j.prototype, {
        chain: function () {
            return this._chain = !0, this
        },
        value: function () {
            return this._wrapped
        }
    })
}.call(this),
function () {
    var t = this,
        e = t.Backbone,
        i = [];
    i.push;
    var s = i.slice;
    i.splice;
    var a;
    a = "undefined" != typeof exports ? exports : t.Backbone = {}, a.VERSION = "1.1.0";
    var h = t._;
    h || "undefined" == typeof require || (h = require("underscore")), a.$ = t.jQuery || t.Zepto || t.ender || t.$, a.noConflict = function () {
        return t.Backbone = e, this
    }, a.emulateHTTP = !1, a.emulateJSON = !1;
    var o = a.Events = {
            on: function (t, e, i) {
                if (!l(this, "on", t, [e, i]) || !e) return this;
                this._events || (this._events = {});
                var r = this._events[t] || (this._events[t] = []);
                return r.push({
                    callback: e,
                    context: i,
                    ctx: i || this
                }), this
            },
            once: function (t, e, i) {
                if (!l(this, "once", t, [e, i]) || !e) return this;
                var r = this,
                    s = h.once(function () {
                        r.off(t, s), e.apply(this, arguments)
                    });
                return s._callback = e, this.on(t, s, i)
            },
            off: function (t, e, i) {
                var r, s, n, a, o, u, c, f;
                if (!this._events || !l(this, "off", t, [e, i])) return this;
                if (!t && !e && !i) return this._events = {}, this;
                for (a = t ? [t] : h.keys(this._events), o = 0, u = a.length; u > o; o++)
                    if (t = a[o], n = this._events[t]) {
                        if (this._events[t] = r = [], e || i)
                            for (c = 0, f = n.length; f > c; c++) s = n[c], (e && e !== s.callback && e !== s.callback._callback || i && i !== s.context) && r.push(s);
                        r.length || delete this._events[t]
                    }
                return this
            },
            trigger: function (t) {
                if (!this._events) return this;
                var e = s.call(arguments, 1);
                if (!l(this, "trigger", t, e)) return this;
                var i = this._events[t],
                    r = this._events.all;
                return i && c(i, e), r && c(r, arguments), this
            },
            stopListening: function (t, e, i) {
                var r = this._listeningTo;
                if (!r) return this;
                var s = !e && !i;
                i || "object" != typeof e || (i = this), t && ((r = {})[t._listenId] = t);
                for (var n in r) t = r[n], t.off(e, i, this), (s || h.isEmpty(t._events)) && delete this._listeningTo[n];
                return this
            }
        },
        u = /\s+/,
        l = function (t, e, i, r) {
            if (!i) return !0;
            if ("object" == typeof i) {
                for (var s in i) t[e].apply(t, [s, i[s]].concat(r));
                return !1
            }
            if (u.test(i)) {
                for (var n = i.split(u), a = 0, h = n.length; h > a; a++) t[e].apply(t, [n[a]].concat(r));
                return !1
            }
            return !0
        },
        c = function (t, e) {
            var i, r = -1,
                s = t.length,
                n = e[0],
                a = e[1],
                h = e[2];
            switch (e.length) {
            case 0:
                for (; ++r < s;)(i = t[r]).callback.call(i.ctx);
                return;
            case 1:
                for (; ++r < s;)(i = t[r]).callback.call(i.ctx, n);
                return;
            case 2:
                for (; ++r < s;)(i = t[r]).callback.call(i.ctx, n, a);
                return;
            case 3:
                for (; ++r < s;)(i = t[r]).callback.call(i.ctx, n, a, h);
                return;
            default:
                for (; ++r < s;)(i = t[r]).callback.apply(i.ctx, e)
            }
        },
        f = {
            listenTo: "on",
            listenToOnce: "once"
        };
    h.each(f, function (t, e) {
        o[e] = function (e, i, r) {
            var s = this._listeningTo || (this._listeningTo = {}),
                n = e._listenId || (e._listenId = h.uniqueId("l"));
            return s[n] = e, r || "object" != typeof i || (r = this), e[t](i, r, this), this
        }
    }), o.bind = o.on, o.unbind = o.off, h.extend(a, o);
    var d = a.Model = function (t, e) {
        var i = t || {};
        e || (e = {}), this.cid = h.uniqueId("c"), this.attributes = {}, e.collection && (this.collection = e.collection), e.parse && (i = this.parse(i, e) || {}), i = h.defaults({}, i, h.result(this, "defaults")), this.set(i, e), this.changed = {}, this.initialize.apply(this, arguments)
    };
    h.extend(d.prototype, o, {
        changed: null,
        validationError: null,
        idAttribute: "id",
        initialize: function () {},
        toJSON: function () {
            return h.clone(this.attributes)
        },
        sync: function () {
            return a.sync.apply(this, arguments)
        },
        get: function (t) {
            return this.attributes[t]
        },
        escape: function (t) {
            return h.escape(this.get(t))
        },
        has: function (t) {
            return null != this.get(t)
        },
        set: function (t, e, i) {
            var r, s, n, a, o, u, l, c;
            if (null == t) return this;
            if ("object" == typeof t ? (s = t, i = e) : (s = {})[t] = e, i || (i = {}), !this._validate(s, i)) return !1;
            n = i.unset, o = i.silent, a = [], u = this._changing, this._changing = !0, u || (this._previousAttributes = h.clone(this.attributes), this.changed = {}), c = this.attributes, l = this._previousAttributes, this.idAttribute in s && (this.id = s[this.idAttribute]);
            for (r in s) e = s[r], h.isEqual(c[r], e) || a.push(r), h.isEqual(l[r], e) ? delete this.changed[r] : this.changed[r] = e, n ? delete c[r] : c[r] = e;
            if (!o) {
                a.length && (this._pending = !0);
                for (var f = 0, d = a.length; d > f; f++) this.trigger("change:" + a[f], this, c[a[f]], i)
            }
            if (u) return this;
            if (!o)
                for (; this._pending;) this._pending = !1, this.trigger("change", this, i);
            return this._pending = !1, this._changing = !1, this
        },
        unset: function (t, e) {
            return this.set(t, void 0, h.extend({}, e, {
                unset: !0
            }))
        },
        clear: function (t) {
            var e = {};
            for (var i in this.attributes) e[i] = void 0;
            return this.set(e, h.extend({}, t, {
                unset: !0
            }))
        },
        hasChanged: function (t) {
            return null == t ? !h.isEmpty(this.changed) : h.has(this.changed, t)
        },
        changedAttributes: function (t) {
            if (!t) return this.hasChanged() ? h.clone(this.changed) : !1;
            var e, i = !1,
                r = this._changing ? this._previousAttributes : this.attributes;
            for (var s in t) h.isEqual(r[s], e = t[s]) || ((i || (i = {}))[s] = e);
            return i
        },
        previous: function (t) {
            return null != t && this._previousAttributes ? this._previousAttributes[t] : null
        },
        previousAttributes: function () {
            return h.clone(this._previousAttributes)
        },
        fetch: function (t) {
            t = t ? h.clone(t) : {}, void 0 === t.parse && (t.parse = !0);
            var e = this,
                i = t.success;
            return t.success = function (r) {
                return e.set(e.parse(r, t), t) ? (i && i(e, r, t), e.trigger("sync", e, r, t), void 0) : !1
            }, M(this, t), this.sync("read", this, t)
        },
        save: function (t, e, i) {
            var r, s, n, a = this.attributes;
            if (null == t || "object" == typeof t ? (r = t, i = e) : (r = {})[t] = e, i = h.extend({
                validate: !0
            }, i), r && !i.wait) {
                if (!this.set(r, i)) return !1
            } else if (!this._validate(r, i)) return !1;
            r && i.wait && (this.attributes = h.extend({}, a, r)), void 0 === i.parse && (i.parse = !0);
            var o = this,
                u = i.success;
            return i.success = function (t) {
                o.attributes = a;
                var e = o.parse(t, i);
                return i.wait && (e = h.extend(r || {}, e)), h.isObject(e) && !o.set(e, i) ? !1 : (u && u(o, t, i), o.trigger("sync", o, t, i), void 0)
            }, M(this, i), s = this.isNew() ? "create" : i.patch ? "patch" : "update", "patch" === s && (i.attrs = r), n = this.sync(s, this, i), r && i.wait && (this.attributes = a), n
        },
        destroy: function (t) {
            t = t ? h.clone(t) : {};
            var e = this,
                i = t.success,
                r = function () {
                    e.trigger("destroy", e, e.collection, t)
                };
            if (t.success = function (s) {
                (t.wait || e.isNew()) && r(), i && i(e, s, t), e.isNew() || e.trigger("sync", e, s, t)
            }, this.isNew()) return t.success(), !1;
            M(this, t);
            var s = this.sync("delete", this, t);
            return t.wait || r(), s
        },
        url: function () {
            var t = h.result(this, "urlRoot") || h.result(this.collection, "url") || U();
            return this.isNew() ? t : t + ("/" === t.charAt(t.length - 1) ? "" : "/") + encodeURIComponent(this.id)
        },
        parse: function (t) {
            return t
        },
        clone: function () {
            return new this.constructor(this.attributes)
        },
        isNew: function () {
            return null == this.id
        },
        isValid: function (t) {
            return this._validate({}, h.extend(t || {}, {
                validate: !0
            }))
        },
        _validate: function (t, e) {
            if (!e.validate || !this.validate) return !0;
            t = h.extend({}, this.attributes, t);
            var i = this.validationError = this.validate(t, e) || null;
            return i ? (this.trigger("invalid", this, i, h.extend(e, {
                validationError: i
            })), !1) : !0
        }
    });
    var p = ["keys", "values", "pairs", "invert", "pick", "omit"];
    h.each(p, function (t) {
        d.prototype[t] = function () {
            var e = s.call(arguments);
            return e.unshift(this.attributes), h[t].apply(h, e)
        }
    });
    var v = a.Collection = function (t, e) {
            e || (e = {}), e.model && (this.model = e.model), void 0 !== e.comparator && (this.comparator = e.comparator), this._reset(), this.initialize.apply(this, arguments), t && this.reset(t, h.extend({
                silent: !0
            }, e))
        },
        g = {
            add: !0,
            remove: !0,
            merge: !0
        },
        m = {
            add: !0,
            remove: !1
        };
    h.extend(v.prototype, o, {
        model: d,
        initialize: function () {},
        toJSON: function (t) {
            return this.map(function (e) {
                return e.toJSON(t)
            })
        },
        sync: function () {
            return a.sync.apply(this, arguments)
        },
        add: function (t, e) {
            return this.set(t, h.extend({
                merge: !1
            }, e, m))
        },
        remove: function (t, e) {
            var i = !h.isArray(t);
            t = i ? [t] : h.clone(t), e || (e = {});
            var r, s, n, a;
            for (r = 0, s = t.length; s > r; r++) a = t[r] = this.get(t[r]), a && (delete this._byId[a.id], delete this._byId[a.cid], n = this.indexOf(a), this.models.splice(n, 1), this.length--, e.silent || (e.index = n, a.trigger("remove", a, this, e)), this._removeReference(a));
            return i ? t[0] : t
        },
        set: function (t, e) {
            e = h.defaults({}, e, g), e.parse && (t = this.parse(t, e));
            var i = !h.isArray(t);
            t = i ? t ? [t] : [] : h.clone(t);
            var r, s, n, a, o, u, l, c = e.at,
                f = this.model,
                p = this.comparator && null == c && e.sort !== !1,
                v = h.isString(this.comparator) ? this.comparator : null,
                m = [],
                y = [],
                _ = {},
                w = e.add,
                b = e.merge,
                x = e.remove,
                E = !p && w && x ? [] : !1;
            for (r = 0, s = t.length; s > r; r++) {
                if (o = t[r], n = o instanceof d ? a = o : o[f.prototype.idAttribute], u = this.get(n)) x && (_[u.cid] = !0), b && (o = o === a ? a.attributes : o, e.parse && (o = u.parse(o, e)), u.set(o, e), p && !l && u.hasChanged(v) && (l = !0)), t[r] = u;
                else if (w) {
                    if (a = t[r] = this._prepareModel(o, e), !a) continue;
                    m.push(a), a.on("all", this._onModelEvent, this), this._byId[a.cid] = a, null != a.id && (this._byId[a.id] = a)
                }
                E && E.push(u || a)
            }
            if (x) {
                for (r = 0, s = this.length; s > r; ++r) _[(a = this.models[r]).cid] || y.push(a);
                y.length && this.remove(y, e)
            }
            if (m.length || E && E.length)
                if (p && (l = !0), this.length += m.length, null != c)
                    for (r = 0, s = m.length; s > r; r++) this.models.splice(c + r, 0, m[r]);
                else {
                    E && (this.models.length = 0);
                    var T = E || m;
                    for (r = 0, s = T.length; s > r; r++) this.models.push(T[r])
                }
            if (l && this.sort({
                silent: !0
            }), !e.silent) {
                for (r = 0, s = m.length; s > r; r++)(a = m[r]).trigger("add", a, this, e);
                (l || E && E.length) && this.trigger("sort", this, e)
            }
            return i ? t[0] : t
        },
        reset: function (t, e) {
            e || (e = {});
            for (var i = 0, r = this.models.length; r > i; i++) this._removeReference(this.models[i]);
            return e.previousModels = this.models, this._reset(), t = this.add(t, h.extend({
                silent: !0
            }, e)), e.silent || this.trigger("reset", this, e), t
        },
        push: function (t, e) {
            return this.add(t, h.extend({
                at: this.length
            }, e))
        },
        pop: function (t) {
            var e = this.at(this.length - 1);
            return this.remove(e, t), e
        },
        unshift: function (t, e) {
            return this.add(t, h.extend({
                at: 0
            }, e))
        },
        shift: function (t) {
            var e = this.at(0);
            return this.remove(e, t), e
        },
        slice: function () {
            return s.apply(this.models, arguments)
        },
        get: function (t) {
            return null == t ? void 0 : this._byId[t.id] || this._byId[t.cid] || this._byId[t]
        },
        at: function (t) {
            return this.models[t]
        },
        where: function (t, e) {
            return h.isEmpty(t) ? e ? void 0 : [] : this[e ? "find" : "filter"](function (e) {
                for (var i in t)
                    if (t[i] !== e.get(i)) return !1;
                return !0
            })
        },
        findWhere: function (t) {
            return this.where(t, !0)
        },
        sort: function (t) {
            if (!this.comparator) throw new Error("Cannot sort a set without a comparator");
            return t || (t = {}), h.isString(this.comparator) || 1 === this.comparator.length ? this.models = this.sortBy(this.comparator, this) : this.models.sort(h.bind(this.comparator, this)), t.silent || this.trigger("sort", this, t), this
        },
        pluck: function (t) {
            return h.invoke(this.models, "get", t)
        },
        fetch: function (t) {
            t = t ? h.clone(t) : {}, void 0 === t.parse && (t.parse = !0);
            var e = t.success,
                i = this;
            return t.success = function (r) {
                var s = t.reset ? "reset" : "set";
                i[s](r, t), e && e(i, r, t), i.trigger("sync", i, r, t)
            }, M(this, t), this.sync("read", this, t)
        },
        create: function (t, e) {
            if (e = e ? h.clone(e) : {}, !(t = this._prepareModel(t, e))) return !1;
            e.wait || this.add(t, e);
            var i = this,
                r = e.success;
            return e.success = function (t, e, s) {
                s.wait && i.add(t, s), r && r(t, e, s)
            }, t.save(null, e), t
        },
        parse: function (t) {
            return t
        },
        clone: function () {
            return new this.constructor(this.models)
        },
        _reset: function () {
            this.length = 0, this.models = [], this._byId = {}
        },
        _prepareModel: function (t, e) {
            if (t instanceof d) return t.collection || (t.collection = this), t;
            e = e ? h.clone(e) : {}, e.collection = this;
            var i = new this.model(t, e);
            return i.validationError ? (this.trigger("invalid", this, i.validationError, e), !1) : i
        },
        _removeReference: function (t) {
            this === t.collection && delete t.collection, t.off("all", this._onModelEvent, this)
        },
        _onModelEvent: function (t, e, i, r) {
            ("add" !== t && "remove" !== t || i === this) && ("destroy" === t && this.remove(e, r), e && t === "change:" + e.idAttribute && (delete this._byId[e.previous(e.idAttribute)], null != e.id && (this._byId[e.id] = e)), this.trigger.apply(this, arguments))
        }
    });
    var y = ["forEach", "each", "map", "collect", "reduce", "foldl", "inject", "reduceRight", "foldr", "find", "detect", "filter", "select", "reject", "every", "all", "some", "any", "include", "contains", "invoke", "max", "min", "toArray", "size", "first", "head", "take", "initial", "rest", "tail", "drop", "last", "without", "difference", "indexOf", "shuffle", "lastIndexOf", "isEmpty", "chain"];
    h.each(y, function (t) {
        v.prototype[t] = function () {
            var e = s.call(arguments);
            return e.unshift(this.models), h[t].apply(h, e)
        }
    });
    var _ = ["groupBy", "countBy", "sortBy"];
    h.each(_, function (t) {
        v.prototype[t] = function (e, i) {
            var r = h.isFunction(e) ? e : function (t) {
                return t.get(e)
            };
            return h[t](this.models, r, i)
        }
    });
    var w = a.View = function (t) {
            this.cid = h.uniqueId("view"), t || (t = {}), h.extend(this, h.pick(t, x)), this._ensureElement(), this.initialize.apply(this, arguments), this.delegateEvents()
        },
        b = /^(\S+)\s*(.*)$/,
        x = ["model", "collection", "el", "id", "attributes", "className", "tagName", "events"];
    h.extend(w.prototype, o, {
        tagName: "div",
        $: function (t) {
            return this.$el.find(t)
        },
        initialize: function () {},
        render: function () {
            return this
        },
        remove: function () {
            return this.$el.remove(), this.stopListening(), this
        },
        setElement: function (t, e) {
            return this.$el && this.undelegateEvents(), this.$el = t instanceof a.$ ? t : a.$(t), this.el = this.$el[0], e !== !1 && this.delegateEvents(), this
        },
        delegateEvents: function (t) {
            if (!t && !(t = h.result(this, "events"))) return this;
            this.undelegateEvents();
            for (var e in t) {
                var i = t[e];
                if (h.isFunction(i) || (i = this[t[e]]), i) {
                    var r = e.match(b),
                        s = r[1],
                        n = r[2];
                    i = h.bind(i, this), s += ".delegateEvents" + this.cid, "" === n ? this.$el.on(s, i) : this.$el.on(s, n, i)
                }
            }
            return this
        },
        undelegateEvents: function () {
            return this.$el.off(".delegateEvents" + this.cid), this
        },
        _ensureElement: function () {
            if (this.el) this.setElement(h.result(this, "el"), !1);
            else {
                var t = h.extend({}, h.result(this, "attributes"));
                this.id && (t.id = h.result(this, "id")), this.className && (t["class"] = h.result(this, "className"));
                var e = a.$("<" + h.result(this, "tagName") + ">").attr(t);
                this.setElement(e, !1)
            }
        }
    }), a.sync = function (t, e, i) {
        var r = T[t];
        h.defaults(i || (i = {}), {
            emulateHTTP: a.emulateHTTP,
            emulateJSON: a.emulateJSON
        });
        var s = {
            type: r,
            dataType: "json"
        };
        if (i.url || (s.url = h.result(e, "url") || U()), null != i.data || !e || "create" !== t && "update" !== t && "patch" !== t || (s.contentType = "application/json", s.data = JSON.stringify(i.attrs || e.toJSON(i))), i.emulateJSON && (s.contentType = "application/x-www-form-urlencoded", s.data = s.data ? {
            model: s.data
        } : {}), i.emulateHTTP && ("PUT" === r || "DELETE" === r || "PATCH" === r)) {
            s.type = "POST", i.emulateJSON && (s.data._method = r);
            var n = i.beforeSend;
            i.beforeSend = function (t) {
                return t.setRequestHeader("X-HTTP-Method-Override", r), n ? n.apply(this, arguments) : void 0
            }
        }
        "GET" === s.type || i.emulateJSON || (s.processData = !1), "PATCH" === s.type && E && (s.xhr = function () {
            return new ActiveXObject("Microsoft.XMLHTTP")
        });
        var o = i.xhr = a.ajax(h.extend(s, i));
        return e.trigger("request", e, o, i), o
    };
    var E = !("undefined" == typeof window || !window.ActiveXObject || window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent),
        T = {
            create: "POST",
            update: "PUT",
            patch: "PATCH",
            "delete": "DELETE",
            read: "GET"
        };
    a.ajax = function () {
        return a.$.ajax.apply(a.$, arguments)
    };
    var k = a.Router = function (t) {
            t || (t = {}), t.routes && (this.routes = t.routes), this._bindRoutes(), this.initialize.apply(this, arguments)
        },
        S = /\((.*?)\)/g,
        $ = /(\(\?)?:\w+/g,
        H = /\*\w+/g,
        A = /[\-{}\[\]+?.,\\\^$|#\s]/g;
    h.extend(k.prototype, o, {
        initialize: function () {},
        route: function (t, e, i) {
            h.isRegExp(t) || (t = this._routeToRegExp(t)), h.isFunction(e) && (i = e, e = ""), i || (i = this[e]);
            var r = this;
            return a.history.route(t, function (s) {
                var n = r._extractParameters(t, s);
                i && i.apply(r, n), r.trigger.apply(r, ["route:" + e].concat(n)), r.trigger("route", e, n), a.history.trigger("route", r, e, n)
            }), this
        },
        navigate: function (t, e) {
            return a.history.navigate(t, e), this
        },
        _bindRoutes: function () {
            if (this.routes) {
                this.routes = h.result(this, "routes");
                for (var t, e = h.keys(this.routes); null != (t = e.pop());) this.route(t, this.routes[t])
            }
        },
        _routeToRegExp: function (t) {
            return t = t.replace(A, "\\$&").replace(S, "(?:$1)?").replace($, function (t, e) {
                return e ? t : "([^/]+)"
            }).replace(H, "(.*?)"), new RegExp("^" + t + "$")
        },
        _extractParameters: function (t, e) {
            var i = t.exec(e).slice(1);
            return h.map(i, function (t) {
                return t ? decodeURIComponent(t) : null
            })
        }
    });
    var I = a.History = function () {
            this.handlers = [], h.bindAll(this, "checkUrl"), "undefined" != typeof window && (this.location = window.location, this.history = window.history)
        },
        N = /^[#\/]|\s+$/g,
        O = /^\/+|\/+$/g,
        P = /msie [\w.]+/,
        C = /\/$/,
        j = /[?#].*$/;
    I.started = !1, h.extend(I.prototype, o, {
        interval: 50,
        getHash: function (t) {
            var e = (t || this).location.href.match(/#(.*)$/);
            return e ? e[1] : ""
        },
        getFragment: function (t, e) {
            if (null == t)
                if (this._hasPushState || !this._wantsHashChange || e) {
                    t = this.location.pathname;
                    var i = this.root.replace(C, "");
                    t.indexOf(i) || (t = t.slice(i.length))
                } else t = this.getHash();
            return t.replace(N, "")
        },
        start: function (t) {
            if (I.started) throw new Error("Backbone.history has already been started");
            I.started = !0, this.options = h.extend({
                root: "/"
            }, this.options, t), this.root = this.options.root, this._wantsHashChange = this.options.hashChange !== !1, this._wantsPushState = !!this.options.pushState, this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState);
            var e = this.getFragment(),
                i = document.documentMode,
                r = P.exec(navigator.userAgent.toLowerCase()) && (!i || 7 >= i);
            this.root = ("/" + this.root + "/").replace(O, "/"), r && this._wantsHashChange && (this.iframe = a.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow, this.navigate(e)), this._hasPushState ? a.$(window).on("popstate", this.checkUrl) : this._wantsHashChange && "onhashchange" in window && !r ? a.$(window).on("hashchange", this.checkUrl) : this._wantsHashChange && (this._checkUrlInterval = setInterval(this.checkUrl, this.interval)), this.fragment = e;
            var s = this.location,
                n = s.pathname.replace(/[^\/]$/, "$&/") === this.root;
            if (this._wantsHashChange && this._wantsPushState) {
                if (!this._hasPushState && !n) return this.fragment = this.getFragment(null, !0), this.location.replace(this.root + this.location.search + "#" + this.fragment), !0;
                this._hasPushState && n && s.hash && (this.fragment = this.getHash().replace(N, ""), this.history.replaceState({}, document.title, this.root + this.fragment + s.search))
            }
            return this.options.silent ? void 0 : this.loadUrl()
        },
        stop: function () {
            a.$(window).off("popstate", this.checkUrl).off("hashchange", this.checkUrl), clearInterval(this._checkUrlInterval), I.started = !1
        },
        route: function (t, e) {
            this.handlers.unshift({
                route: t,
                callback: e
            })
        },
        checkUrl: function () {
            var e = this.getFragment();
            return e === this.fragment && this.iframe && (e = this.getFragment(this.getHash(this.iframe))), e === this.fragment ? !1 : (this.iframe && this.navigate(e), this.loadUrl(), void 0)
        },
        loadUrl: function (t) {
            return t = this.fragment = this.getFragment(t), h.any(this.handlers, function (e) {
                return e.route.test(t) ? (e.callback(t), !0) : void 0
            })
        },
        navigate: function (t, e) {
            if (!I.started) return !1;
            e && e !== !0 || (e = {
                trigger: !!e
            });
            var i = this.root + (t = this.getFragment(t || ""));
            if (t = t.replace(j, ""), this.fragment !== t) {
                if (this.fragment = t, "" === t && "/" !== i && (i = i.slice(0, -1)), this._hasPushState) this.history[e.replace ? "replaceState" : "pushState"]({}, document.title, i);
                else {
                    if (!this._wantsHashChange) return this.location.assign(i);
                    this._updateHash(this.location, t, e.replace), this.iframe && t !== this.getFragment(this.getHash(this.iframe)) && (e.replace || this.iframe.document.open().close(), this._updateHash(this.iframe.location, t, e.replace))
                }
                return e.trigger ? this.loadUrl(t) : void 0
            }
        },
        _updateHash: function (t, e, i) {
            if (i) {
                var r = t.href.replace(/(javascript:|#).*$/, "");
                t.replace(r + "#" + e)
            } else t.hash = "#" + e
        }
    }), a.history = new I;
    var R = function (t, e) {
        var r, i = this;
        r = t && h.has(t, "constructor") ? t.constructor : function () {
            return i.apply(this, arguments)
        }, h.extend(r, i, e);
        var s = function () {
            this.constructor = r
        };
        return s.prototype = i.prototype, r.prototype = new s, t && h.extend(r.prototype, t), r.__super__ = i.prototype, r
    };
    d.extend = v.extend = k.extend = w.extend = I.extend = R;
    var U = function () {
            throw new Error('A "url" property or function must be specified')
        },
        M = function (t, e) {
            var i = e.error;
            e.error = function (r) {
                i && i(t, r, e), t.trigger("error", t, r, e)
            }
        }
}.call(this), Backbone.ChildViewContainer = function (a, b) {
    var c = function (a) {
        this._views = {}, this._indexByModel = {}, this._indexByCustom = {}, this._updateLength(), b.each(a, this.add, this)
    };
    b.extend(c.prototype, {
        add: function (a, b) {
            var c = a.cid;
            this._views[c] = a, a.model && (this._indexByModel[a.model.cid] = c), b && (this._indexByCustom[b] = c), this._updateLength()
        },
        findByModel: function (a) {
            return this.findByModelCid(a.cid)
        },
        findByModelCid: function (a) {
            var b = this._indexByModel[a];
            return this.findByCid(b)
        },
        findByCustom: function (a) {
            var b = this._indexByCustom[a];
            return this.findByCid(b)
        },
        findByIndex: function (a) {
            return b.values(this._views)[a]
        },
        findByCid: function (a) {
            return this._views[a]
        },
        remove: function (a) {
            var c = a.cid;
            a.model && delete this._indexByModel[a.model.cid], b.any(this._indexByCustom, function (a, b) {
                return a === c ? (delete this._indexByCustom[b], !0) : void 0
            }, this), delete this._views[c], this._updateLength()
        },
        call: function (a) {
            this.apply(a, b.tail(arguments))
        },
        apply: function (a, c) {
            b.each(this._views, function (d) {
                b.isFunction(d[a]) && d[a].apply(d, c || [])
            })
        },
        _updateLength: function () {
            this.length = b.size(this._views)
        }
    });
    var d = ["forEach", "each", "map", "find", "detect", "filter", "select", "reject", "every", "all", "some", "any", "include", "contains", "invoke", "toArray", "first", "initial", "rest", "last", "without", "isEmpty", "pluck"];
    return b.each(d, function (a) {
        c.prototype[a] = function () {
            var c = b.values(this._views),
                d = [c].concat(b.toArray(arguments));
            return b[a].apply(b, d)
        }
    }), c
}(Backbone, _), Backbone.Wreqr = function (a, b, c) {
    "use strict";
    var d = {};
    return d.Handlers = function (a, b) {
        var c = function (a) {
            this.options = a, this._wreqrHandlers = {}, b.isFunction(this.initialize) && this.initialize(a)
        };
        return c.extend = a.Model.extend, b.extend(c.prototype, a.Events, {
            setHandlers: function (a) {
                b.each(a, function (a, c) {
                    var d = null;
                    b.isObject(a) && !b.isFunction(a) && (d = a.context, a = a.callback), this.setHandler(c, a, d)
                }, this)
            },
            setHandler: function (a, b, c) {
                var d = {
                    callback: b,
                    context: c
                };
                this._wreqrHandlers[a] = d, this.trigger("handler:add", a, b, c)
            },
            hasHandler: function (a) {
                return !!this._wreqrHandlers[a]
            },
            getHandler: function (a) {
                var b = this._wreqrHandlers[a];
                if (!b) throw new Error("Handler not found for '" + a + "'");
                return function () {
                    var a = Array.prototype.slice.apply(arguments);
                    return b.callback.apply(b.context, a)
                }
            },
            removeHandler: function (a) {
                delete this._wreqrHandlers[a]
            },
            removeAllHandlers: function () {
                this._wreqrHandlers = {}
            }
        }), c
    }(a, c), d.CommandStorage = function () {
        var b = function (a) {
            this.options = a, this._commands = {}, c.isFunction(this.initialize) && this.initialize(a)
        };
        return c.extend(b.prototype, a.Events, {
            getCommands: function (a) {
                var b = this._commands[a];
                return b || (b = {
                    command: a,
                    instances: []
                }, this._commands[a] = b), b
            },
            addCommand: function (a, b) {
                var c = this.getCommands(a);
                c.instances.push(b)
            },
            clearCommands: function (a) {
                var b = this.getCommands(a);
                b.instances = []
            }
        }), b
    }(), d.Commands = function (a) {
        return a.Handlers.extend({
            storageType: a.CommandStorage,
            constructor: function (b) {
                this.options = b || {}, this._initializeStorage(this.options), this.on("handler:add", this._executeCommands, this);
                var c = Array.prototype.slice.call(arguments);
                a.Handlers.prototype.constructor.apply(this, c)
            },
            execute: function (a, b) {
                a = arguments[0], b = Array.prototype.slice.call(arguments, 1), this.hasHandler(a) ? this.getHandler(a).apply(this, b) : this.storage.addCommand(a, b)
            },
            _executeCommands: function (a, b, d) {
                var e = this.storage.getCommands(a);
                c.each(e.instances, function (a) {
                    b.apply(d, a)
                }), this.storage.clearCommands(a)
            },
            _initializeStorage: function (a) {
                var b, d = a.storageType || this.storageType;
                b = c.isFunction(d) ? new d : d, this.storage = b
            }
        })
    }(d), d.RequestResponse = function (a) {
        return a.Handlers.extend({
            request: function () {
                var a = arguments[0],
                    b = Array.prototype.slice.call(arguments, 1);
                return this.getHandler(a).apply(this, b)
            }
        })
    }(d), d.EventAggregator = function (a, b) {
        var c = function () {};
        return c.extend = a.Model.extend, b.extend(c.prototype, a.Events), c
    }(a, c), d
}(Backbone, Backbone.Marionette, _);
var Marionette = function (a, b, c) {
    "use strict";

    function d(a) {
        return g.call(a)
    }

    function e(a, b) {
        var c = new Error(a);
        throw c.name = b || "Error", c
    }
    var f = {};
    b.Marionette = f, f.$ = b.$;
    var g = Array.prototype.slice;
    return f.extend = b.Model.extend, f.getOption = function (a, b) {
            if (a && b) {
                var c;
                return c = a.options && b in a.options && void 0 !== a.options[b] ? a.options[b] : a[b]
            }
        }, f.triggerMethod = function () {
            function a(a, b, c) {
                return c.toUpperCase()
            }
            var b = /(^|:)(\w)/gi,
                d = function (d) {
                    var e = "on" + d.replace(b, a),
                        f = this[e];
                    return c.isFunction(this.trigger) && this.trigger.apply(this, arguments), c.isFunction(f) ? f.apply(this, c.tail(arguments)) : void 0
                };
            return d
        }(), f.MonitorDOMRefresh = function (a) {
            function b(a) {
                a._isShown = !0, e(a)
            }

            function d(a) {
                a._isRendered = !0, e(a)
            }

            function e(a) {
                a._isShown && a._isRendered && f(a) && c.isFunction(a.triggerMethod) && a.triggerMethod("dom:refresh")
            }

            function f(b) {
                return a.contains(b.el)
            }
            return function (a) {
                a.listenTo(a, "show", function () {
                    b(a)
                }), a.listenTo(a, "render", function () {
                    d(a)
                })
            }
        }(document.documentElement),
        function (a) {
            function b(a, b, d, f) {
                var g = f.split(/\s+/);
                c.each(g, function (c) {
                    var f = a[c];
                    f || e("Method '" + c + "' was configured as an event handler, but does not exist."), a.listenTo(b, d, f, a)
                })
            }

            function d(a, b, c, d) {
                a.listenTo(b, c, d, a)
            }

            function f(a, b, d, e) {
                var f = e.split(/\s+/);
                c.each(f, function (c) {
                    var e = a[c];
                    a.stopListening(b, d, e, a)
                })
            }

            function g(a, b, c, d) {
                a.stopListening(b, c, d, a)
            }

            function h(a, b, d, e, f) {
                b && d && (c.isFunction(d) && (d = d.call(a)), c.each(d, function (d, g) {
                    c.isFunction(d) ? e(a, b, g, d) : f(a, b, g, d)
                }))
            }
            a.bindEntityEvents = function (a, c, e) {
                h(a, c, e, d, b)
            }, a.unbindEntityEvents = function (a, b, c) {
                h(a, b, c, g, f)
            }
        }(f), f.Callbacks = function () {
            this._deferred = f.$.Deferred(), this._callbacks = []
        }, c.extend(f.Callbacks.prototype, {
            add: function (a, b) {
                this._callbacks.push({
                    cb: a,
                    ctx: b
                }), this._deferred.done(function (c, d) {
                    b && (c = b), a.call(c, d)
                })
            },
            run: function (a, b) {
                this._deferred.resolve(b, a)
            },
            reset: function () {
                var a = this._callbacks;
                this._deferred = f.$.Deferred(), this._callbacks = [], c.each(a, function (a) {
                    this.add(a.cb, a.ctx)
                }, this)
            }
        }), f.Controller = function (a) {
            this.triggerMethod = f.triggerMethod, this.options = a || {}, c.isFunction(this.initialize) && this.initialize(this.options)
        }, f.Controller.extend = f.extend, c.extend(f.Controller.prototype, b.Events, {
            close: function () {
                this.stopListening(), this.triggerMethod("close"), this.unbind()
            }
        }), f.Region = function (a) {
            if (this.options = a || {}, this.el = f.getOption(this, "el"), !this.el) {
                var b = new Error("An 'el' must be specified for a region.");
                throw b.name = "NoElError", b
            }
            if (this.initialize) {
                var c = Array.prototype.slice.apply(arguments);
                this.initialize.apply(this, c)
            }
        }, c.extend(f.Region, {
            buildRegion: function (a, b) {
                var d = "string" == typeof a,
                    e = "string" == typeof a.selector,
                    f = "undefined" == typeof a.regionType,
                    g = "function" == typeof a;
                if (!g && !d && !e) throw new Error("Region must be specified as a Region type, a selector string or an object with selector property");
                var h, i;
                d && (h = a), a.selector && (h = a.selector, delete a.selector), g && (i = a), !g && f && (i = b), a.regionType && (i = a.regionType, delete a.regionType), (d || g) && (a = {}), a.el = h;
                var j = new i(a);
                return a.parentEl && (j.getEl = function (b) {
                    var d = a.parentEl;
                    return c.isFunction(d) && (d = d()), d.find(b)
                }), j
            }
        }), c.extend(f.Region.prototype, b.Events, {
            show: function (a) {
                this.ensureEl();
                var b = a.isClosed || c.isUndefined(a.$el),
                    d = a !== this.currentView;
                d && this.close(), a.render(), (d || b) && this.open(a), this.currentView = a, f.triggerMethod.call(this, "show", a), f.triggerMethod.call(a, "show")
            },
            ensureEl: function () {
                this.$el && 0 !== this.$el.length || (this.$el = this.getEl(this.el))
            },
            getEl: function (a) {
                return f.$(a)
            },
            open: function (a) {
                this.$el.empty().append(a.el)
            },
            close: function () {
                var a = this.currentView;
                a && !a.isClosed && (a.close ? a.close() : a.remove && a.remove(), f.triggerMethod.call(this, "close", a), delete this.currentView)
            },
            attachView: function (a) {
                this.currentView = a
            },
            reset: function () {
                this.close(), delete this.$el
            }
        }), f.Region.extend = f.extend, f.RegionManager = function (a) {
            var b = a.Controller.extend({
                    constructor: function (b) {
                        this._regions = {}, a.Controller.prototype.constructor.call(this, b)
                    },
                    addRegions: function (a, b) {
                        var d = {};
                        return c.each(a, function (a, e) {
                            "string" == typeof a && (a = {
                                selector: a
                            }), a.selector && (a = c.defaults({}, a, b));
                            var f = this.addRegion(e, a);
                            d[e] = f
                        }, this), d
                    },
                    addRegion: function (b, d) {
                        var e, f = c.isObject(d),
                            g = c.isString(d),
                            h = !!d.selector;
                        return e = g || f && h ? a.Region.buildRegion(d, a.Region) : c.isFunction(d) ? a.Region.buildRegion(d, a.Region) : d, this._store(b, e), this.triggerMethod("region:add", b, e), e
                    },
                    get: function (a) {
                        return this._regions[a]
                    },
                    removeRegion: function (a) {
                        var b = this._regions[a];
                        this._remove(a, b)
                    },
                    removeRegions: function () {
                        c.each(this._regions, function (a, b) {
                            this._remove(b, a)
                        }, this)
                    },
                    closeRegions: function () {
                        c.each(this._regions, function (a) {
                            a.close()
                        }, this)
                    },
                    close: function () {
                        this.removeRegions();
                        var b = Array.prototype.slice.call(arguments);
                        a.Controller.prototype.close.apply(this, b)
                    },
                    _store: function (a, b) {
                        this._regions[a] = b, this._setLength()
                    },
                    _remove: function (a, b) {
                        b.close(), delete this._regions[a], this._setLength(), this.triggerMethod("region:remove", a, b)
                    },
                    _setLength: function () {
                        this.length = c.size(this._regions)
                    }
                }),
                d = ["forEach", "each", "map", "find", "detect", "filter", "select", "reject", "every", "all", "some", "any", "include", "contains", "invoke", "toArray", "first", "initial", "rest", "last", "without", "isEmpty", "pluck"];
            return c.each(d, function (a) {
                b.prototype[a] = function () {
                    var b = c.values(this._regions),
                        d = [b].concat(c.toArray(arguments));
                    return c[a].apply(c, d)
                }
            }), b
        }(f), f.TemplateCache = function (a) {
            this.templateId = a
        }, c.extend(f.TemplateCache, {
            templateCaches: {},
            get: function (a) {
                var b = this.templateCaches[a];
                return b || (b = new f.TemplateCache(a), this.templateCaches[a] = b), b.load()
            },
            clear: function () {
                var a, b = d(arguments),
                    c = b.length;
                if (c > 0)
                    for (a = 0; c > a; a++) delete this.templateCaches[b[a]];
                else this.templateCaches = {}
            }
        }), c.extend(f.TemplateCache.prototype, {
            load: function () {
                if (this.compiledTemplate) return this.compiledTemplate;
                var a = this.loadTemplate(this.templateId);
                return this.compiledTemplate = this.compileTemplate(a), this.compiledTemplate
            },
            loadTemplate: function (a) {
                var b = f.$(a).html();
                return b && 0 !== b.length || e("Could not find template: '" + a + "'", "NoTemplateError"), b
            },
            compileTemplate: function (a) {
                return c.template(a)
            }
        }), f.Renderer = {
            render: function (a, b) {
                if (!a) {
                    var c = new Error("Cannot render the template since it's false, null or undefined.");
                    throw c.name = "TemplateNotFoundError", c
                }
                var d;
                return d = "function" == typeof a ? a : f.TemplateCache.get(a), d(b)
            }
        }, f.View = b.View.extend({
            constructor: function (a) {
                c.bindAll(this, "render");
                var d = Array.prototype.slice.apply(arguments);
                this.options = c.extend({}, c.result(this, "options"), c.isFunction(a) ? a.call(this) : a), this.events = this.normalizeUIKeys(c.result(this, "events")), b.View.prototype.constructor.apply(this, d), f.MonitorDOMRefresh(this), this.listenTo(this, "show", this.onShowCalled, this)
            },
            triggerMethod: f.triggerMethod,
            getTemplate: function () {
                return f.getOption(this, "template")
            },
            mixinTemplateHelpers: function (a) {
                a = a || {};
                var b = f.getOption(this, "templateHelpers");
                return c.isFunction(b) && (b = b.call(this)), c.extend(a, b)
            },
            normalizeUIKeys: function (a) {
                return "undefined" != typeof a ? (c.each(c.keys(a), function (b) {
                    var c = b.split("@ui.");
                    2 === c.length && (a[c[0] + this.ui[c[1]]] = a[b], delete a[b])
                }, this), a) : void 0
            },
            configureTriggers: function () {
                if (this.triggers) {
                    var a = {},
                        b = this.normalizeUIKeys(c.result(this, "triggers"));
                    return c.each(b, function (b, d) {
                        var e = c.isObject(b),
                            f = e ? b.event : b;
                        a[d] = function (a) {
                            if (a) {
                                var c = a.preventDefault,
                                    d = a.stopPropagation,
                                    g = e ? b.preventDefault : c,
                                    h = e ? b.stopPropagation : d;
                                g && c && c.apply(a), h && d && d.apply(a)
                            }
                            var i = {
                                view: this,
                                model: this.model,
                                collection: this.collection
                            };
                            this.triggerMethod(f, i)
                        }
                    }, this), a
                }
            },
            delegateEvents: function (a) {
                this._delegateDOMEvents(a), f.bindEntityEvents(this, this.model, f.getOption(this, "modelEvents")), f.bindEntityEvents(this, this.collection, f.getOption(this, "collectionEvents"))
            },
            _delegateDOMEvents: function (a) {
                a = a || this.events, c.isFunction(a) && (a = a.call(this));
                var d = {},
                    e = this.configureTriggers();
                c.extend(d, a, e), b.View.prototype.delegateEvents.call(this, d)
            },
            undelegateEvents: function () {
                var a = Array.prototype.slice.call(arguments);
                b.View.prototype.undelegateEvents.apply(this, a), f.unbindEntityEvents(this, this.model, f.getOption(this, "modelEvents")), f.unbindEntityEvents(this, this.collection, f.getOption(this, "collectionEvents"))
            },
            onShowCalled: function () {},
            close: function () {
                if (!this.isClosed) {
                    var a = this.triggerMethod("before:close");
                    a !== !1 && (this.isClosed = !0, this.triggerMethod("close"), this.unbindUIElements(), this.remove())
                }
            },
            bindUIElements: function () {
                if (this.ui) {
                    this._uiBindings || (this._uiBindings = this.ui);
                    var a = c.result(this, "_uiBindings");
                    this.ui = {}, c.each(c.keys(a), function (b) {
                        var c = a[b];
                        this.ui[b] = this.$(c)
                    }, this)
                }
            },
            unbindUIElements: function () {
                this.ui && this._uiBindings && (c.each(this.ui, function (a, b) {
                    delete this.ui[b]
                }, this), this.ui = this._uiBindings, delete this._uiBindings)
            }
        }), f.ItemView = f.View.extend({
            constructor: function () {
                f.View.prototype.constructor.apply(this, d(arguments))
            },
            serializeData: function () {
                var a = {};
                return this.model ? a = this.model.toJSON() : this.collection && (a = {
                    items: this.collection.toJSON()
                }), a
            },
            render: function () {
                this.isClosed = !1, this.triggerMethod("before:render", this), this.triggerMethod("item:before:render", this);
                var a = this.serializeData();
                a = this.mixinTemplateHelpers(a);
                var b = this.getTemplate(),
                    c = f.Renderer.render(b, a);
                return this.$el.html(c), this.bindUIElements(), this.triggerMethod("render", this), this.triggerMethod("item:rendered", this), this
            },
            close: function () {
                this.isClosed || (this.triggerMethod("item:before:close"), f.View.prototype.close.apply(this, d(arguments)), this.triggerMethod("item:closed"))
            }
        }), f.CollectionView = f.View.extend({
            itemViewEventPrefix: "itemview",
            constructor: function () {
                this._initChildViewStorage(), f.View.prototype.constructor.apply(this, d(arguments)), this._initialEvents(), this.initRenderBuffer()
            },
            initRenderBuffer: function () {
                this.elBuffer = document.createDocumentFragment(), this._bufferedChildren = []
            },
            startBuffering: function () {
                this.initRenderBuffer(), this.isBuffering = !0
            },
            endBuffering: function () {
                this.isBuffering = !1, this.appendBuffer(this, this.elBuffer), this._triggerShowBufferedChildren(), this.initRenderBuffer()
            },
            _triggerShowBufferedChildren: function () {
                this._isShown && (c.each(this._bufferedChildren, function (a) {
                    f.triggerMethod.call(a, "show")
                }), this._bufferedChildren = [])
            },
            _initialEvents: function () {
                this.collection && (this.listenTo(this.collection, "add", this.addChildView, this), this.listenTo(this.collection, "remove", this.removeItemView, this), this.listenTo(this.collection, "reset", this.render, this))
            },
            addChildView: function (a) {
                this.closeEmptyView();
                var b = this.getItemView(a),
                    c = this.collection.indexOf(a);
                this.addItemView(a, b, c)
            },
            onShowCalled: function () {
                this.children.each(function (a) {
                    f.triggerMethod.call(a, "show")
                })
            },
            triggerBeforeRender: function () {
                this.triggerMethod("before:render", this), this.triggerMethod("collection:before:render", this)
            },
            triggerRendered: function () {
                this.triggerMethod("render", this), this.triggerMethod("collection:rendered", this)
            },
            render: function () {
                return this.isClosed = !1, this.triggerBeforeRender(), this._renderChildren(), this.triggerRendered(), this
            },
            _renderChildren: function () {
                this.startBuffering(), this.closeEmptyView(), this.closeChildren(), this.collection && this.collection.length > 0 ? this.showCollection() : this.showEmptyView(), this.endBuffering()
            },
            showCollection: function () {
                var a;
                this.collection.each(function (b, c) {
                    a = this.getItemView(b), this.addItemView(b, a, c)
                }, this)
            },
            showEmptyView: function () {
                var a = this.getEmptyView();
                if (a && !this._showingEmptyView) {
                    this._showingEmptyView = !0;
                    var c = new b.Model;
                    this.addItemView(c, a, 0)
                }
            },
            closeEmptyView: function () {
                this._showingEmptyView && (this.closeChildren(), delete this._showingEmptyView)
            },
            getEmptyView: function () {
                return f.getOption(this, "emptyView")
            },
            getItemView: function () {
                var a = f.getOption(this, "itemView");
                return a || e("An `itemView` must be specified", "NoItemViewError"), a
            },
            addItemView: function (a, b, d) {
                var e = f.getOption(this, "itemViewOptions");
                c.isFunction(e) && (e = e.call(this, a, d));
                var g = this.buildItemView(a, b, e);
                return this.addChildViewEventForwarding(g), this.triggerMethod("before:item:added", g), this.children.add(g), this.renderItemView(g, d), this._isShown && !this.isBuffering && f.triggerMethod.call(g, "show"), this.triggerMethod("after:item:added", g), g
            },
            addChildViewEventForwarding: function (a) {
                var b = f.getOption(this, "itemViewEventPrefix");
                this.listenTo(a, "all", function () {
                    var e = d(arguments),
                        g = e[0],
                        h = this.getItemEvents();
                    e[0] = b + ":" + g, e.splice(1, 0, a), "undefined" != typeof h && c.isFunction(h[g]) && h[g].apply(this, e), f.triggerMethod.apply(this, e)
                }, this)
            },
            getItemEvents: function () {
                return c.isFunction(this.itemEvents) ? this.itemEvents.call(this) : this.itemEvents
            },
            renderItemView: function (a, b) {
                a.render(), this.appendHtml(this, a, b)
            },
            buildItemView: function (a, b, d) {
                var e = c.extend({
                    model: a
                }, d);
                return new b(e)
            },
            removeItemView: function (a) {
                var b = this.children.findByModel(a);
                this.removeChildView(b), this.checkEmpty()
            },
            removeChildView: function (a) {
                a && (this.stopListening(a), a.close ? a.close() : a.remove && a.remove(), this.children.remove(a)), this.triggerMethod("item:removed", a)
            },
            checkEmpty: function () {
                this.collection && 0 !== this.collection.length || this.showEmptyView()
            },
            appendBuffer: function (a, b) {
                a.$el.append(b)
            },
            appendHtml: function (a, b) {
                a.isBuffering ? (a.elBuffer.appendChild(b.el), a._bufferedChildren.push(b)) : a.$el.append(b.el)
            },
            _initChildViewStorage: function () {
                this.children = new b.ChildViewContainer
            },
            close: function () {
                this.isClosed || (this.triggerMethod("collection:before:close"), this.closeChildren(), this.triggerMethod("collection:closed"), f.View.prototype.close.apply(this, d(arguments)))
            },
            closeChildren: function () {
                this.children.each(function (a) {
                    this.removeChildView(a)
                }, this), this.checkEmpty()
            }
        }), f.CompositeView = f.CollectionView.extend({
            constructor: function () {
                f.CollectionView.prototype.constructor.apply(this, d(arguments))
            },
            _initialEvents: function () {
                this.once("render", function () {
                    this.collection && (this.listenTo(this.collection, "add", this.addChildView, this), this.listenTo(this.collection, "remove", this.removeItemView, this), this.listenTo(this.collection, "reset", this._renderChildren, this))
                })
            },
            getItemView: function () {
                var a = f.getOption(this, "itemView") || this.constructor;
                return a || e("An `itemView` must be specified", "NoItemViewError"), a
            },
            serializeData: function () {
                var a = {};
                return this.model && (a = this.model.toJSON()), a
            },
            render: function () {
                this.isRendered = !0, this.isClosed = !1, this.resetItemViewContainer(), this.triggerBeforeRender();
                var a = this.renderModel();
                return this.$el.html(a), this.bindUIElements(), this.triggerMethod("composite:model:rendered"), this._renderChildren(), this.triggerMethod("composite:rendered"), this.triggerRendered(), this
            },
            _renderChildren: function () {
                this.isRendered && (f.CollectionView.prototype._renderChildren.call(this), this.triggerMethod("composite:collection:rendered"))
            },
            renderModel: function () {
                var a = {};
                a = this.serializeData(), a = this.mixinTemplateHelpers(a);
                var b = this.getTemplate();
                return f.Renderer.render(b, a)
            },
            appendBuffer: function (a, b) {
                var c = this.getItemViewContainer(a);
                c.append(b)
            },
            appendHtml: function (a, b) {
                if (a.isBuffering) a.elBuffer.appendChild(b.el), a._bufferedChildren.push(b);
                else {
                    var c = this.getItemViewContainer(a);
                    c.append(b.el)
                }
            },
            getItemViewContainer: function (a) {
                if ("$itemViewContainer" in a) return a.$itemViewContainer;
                var b, d = f.getOption(a, "itemViewContainer");
                if (d) {
                    var g = c.isFunction(d) ? d.call(this) : d;
                    b = a.$(g), b.length <= 0 && e("The specified `itemViewContainer` was not found: " + a.itemViewContainer, "ItemViewContainerMissingError")
                } else b = a.$el;
                return a.$itemViewContainer = b, b
            },
            resetItemViewContainer: function () {
                this.$itemViewContainer && delete this.$itemViewContainer
            }
        }), f.Layout = f.ItemView.extend({
            regionType: f.Region,
            constructor: function (a) {
                a = a || {}, this._firstRender = !0, this._initializeRegions(a), f.ItemView.prototype.constructor.call(this, a)
            },
            render: function () {
                this.isClosed && this._initializeRegions(), this._firstRender ? this._firstRender = !1 : this.isClosed || this._reInitializeRegions();
                var a = Array.prototype.slice.apply(arguments),
                    b = f.ItemView.prototype.render.apply(this, a);
                return b
            },
            close: function () {
                if (!this.isClosed) {
                    this.regionManager.close();
                    var a = Array.prototype.slice.apply(arguments);
                    f.ItemView.prototype.close.apply(this, a)
                }
            },
            addRegion: function (a, b) {
                var c = {};
                return c[a] = b, this._buildRegions(c)[a]
            },
            addRegions: function (a) {
                return this.regions = c.extend({}, this.regions, a), this._buildRegions(a)
            },
            removeRegion: function (a) {
                return delete this.regions[a], this.regionManager.removeRegion(a)
            },
            _buildRegions: function (a) {
                var b = this,
                    c = {
                        regionType: f.getOption(this, "regionType"),
                        parentEl: function () {
                            return b.$el
                        }
                    };
                return this.regionManager.addRegions(a, c)
            },
            _initializeRegions: function (a) {
                var b;
                this._initRegionManager(), b = c.isFunction(this.regions) ? this.regions(a) : this.regions || {}, this.addRegions(b)
            },
            _reInitializeRegions: function () {
                this.regionManager.closeRegions(), this.regionManager.each(function (a) {
                    a.reset()
                })
            },
            _initRegionManager: function () {
                this.regionManager = new f.RegionManager, this.listenTo(this.regionManager, "region:add", function (a, b) {
                    this[a] = b, this.trigger("region:add", a, b)
                }), this.listenTo(this.regionManager, "region:remove", function (a, b) {
                    delete this[a], this.trigger("region:remove", a, b)
                })
            }
        }), f.AppRouter = b.Router.extend({
            constructor: function (a) {
                b.Router.prototype.constructor.apply(this, d(arguments)), this.options = a || {};
                var c = f.getOption(this, "appRoutes"),
                    e = this._getController();
                this.processAppRoutes(e, c)
            },
            appRoute: function (a, b) {
                var c = this._getController();
                this._addAppRoute(c, a, b)
            },
            processAppRoutes: function (a, b) {
                if (b) {
                    var d = c.keys(b).reverse();
                    c.each(d, function (c) {
                        this._addAppRoute(a, c, b[c])
                    }, this)
                }
            },
            _getController: function () {
                return f.getOption(this, "controller")
            },
            _addAppRoute: function (a, b, d) {
                var e = a[d];
                if (!e) throw new Error("Method '" + d + "' was not found on the controller");
                this.route(b, d, c.bind(e, a))
            }
        }), f.Application = function (a) {
            this._initRegionManager(), this._initCallbacks = new f.Callbacks, this.vent = new b.Wreqr.EventAggregator, this.commands = new b.Wreqr.Commands, this.reqres = new b.Wreqr.RequestResponse, this.submodules = {}, c.extend(this, a), this.triggerMethod = f.triggerMethod
        }, c.extend(f.Application.prototype, b.Events, {
            execute: function () {
                var a = Array.prototype.slice.apply(arguments);
                this.commands.execute.apply(this.commands, a)
            },
            request: function () {
                var a = Array.prototype.slice.apply(arguments);
                return this.reqres.request.apply(this.reqres, a)
            },
            addInitializer: function (a) {
                this._initCallbacks.add(a)
            },
            start: function (a) {
                this.triggerMethod("initialize:before", a), this._initCallbacks.run(a, this), this.triggerMethod("initialize:after", a), this.triggerMethod("start", a)
            },
            addRegions: function (a) {
                return this._regionManager.addRegions(a)
            },
            closeRegions: function () {
                this._regionManager.closeRegions()
            },
            removeRegion: function (a) {
                this._regionManager.removeRegion(a)
            },
            getRegion: function (a) {
                return this._regionManager.get(a)
            },
            module: function () {
                var a = d(arguments);
                return a.unshift(this), f.Module.create.apply(f.Module, a)
            },
            _initRegionManager: function () {
                this._regionManager = new f.RegionManager, this.listenTo(this._regionManager, "region:add", function (a, b) {
                    this[a] = b
                }), this.listenTo(this._regionManager, "region:remove", function (a) {
                    delete this[a]
                })
            }
        }), f.Application.extend = f.extend, f.Module = function (a, b) {
            this.moduleName = a, this.submodules = {}, this._setupInitializersAndFinalizers(), this.app = b, this.startWithParent = !0, this.triggerMethod = f.triggerMethod
        }, c.extend(f.Module.prototype, b.Events, {
            addInitializer: function (a) {
                this._initializerCallbacks.add(a)
            },
            addFinalizer: function (a) {
                this._finalizerCallbacks.add(a)
            },
            start: function (a) {
                this._isInitialized || (c.each(this.submodules, function (b) {
                    b.startWithParent && b.start(a)
                }), this.triggerMethod("before:start", a), this._initializerCallbacks.run(a, this), this._isInitialized = !0, this.triggerMethod("start", a))
            },
            stop: function () {
                this._isInitialized && (this._isInitialized = !1, f.triggerMethod.call(this, "before:stop"), c.each(this.submodules, function (a) {
                    a.stop()
                }), this._finalizerCallbacks.run(void 0, this), this._initializerCallbacks.reset(), this._finalizerCallbacks.reset(), f.triggerMethod.call(this, "stop"))
            },
            addDefinition: function (a, b) {
                this._runModuleDefinition(a, b)
            },
            _runModuleDefinition: function (a, d) {
                if (a) {
                    var e = c.flatten([this, this.app, b, f, f.$, c, d]);
                    a.apply(this, e)
                }
            },
            _setupInitializersAndFinalizers: function () {
                this._initializerCallbacks = new f.Callbacks, this._finalizerCallbacks = new f.Callbacks
            }
        }), c.extend(f.Module, {
            create: function (a, b, e) {
                var f = a,
                    g = d(arguments);
                g.splice(0, 3), b = b.split(".");
                var h = b.length,
                    i = [];
                return i[h - 1] = e, c.each(b, function (b, c) {
                    var d = f;
                    f = this._getModule(d, b, a), this._addModuleDefinition(d, f, i[c], g)
                }, this), f
            },
            _getModule: function (a, b, c) {
                var d = a[b];
                return d || (d = new f.Module(b, c), a[b] = d, a.submodules[b] = d), d
            },
            _addModuleDefinition: function (a, b, d, e) {
                var f, g;
                c.isFunction(d) ? (f = d, g = !0) : c.isObject(d) ? (f = d.define, g = d.startWithParent) : g = !0, f && b.addDefinition(f, e), b.startWithParent = b.startWithParent && g, b.startWithParent && !b.startWithParentIsConfigured && (b.startWithParentIsConfigured = !0, a.addInitializer(function (a) {
                    b.startWithParent && b.start(a)
                }))
            }
        }), f
}(this, Backbone, _);
! function (root, factory) {
    "function" == typeof define && define.amd ? define(["underscore", "backbone"], function (_, Backbone) {
        return factory(_ || root._, Backbone || root.Backbone)
    }) : factory(_, Backbone)
}(this, function (_, Backbone) {
    function S4() {
        return (0 | 65536 * (1 + Math.random())).toString(16).substring(1)
    }

    function guid() {
        return S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()
    }
    return Backbone.LocalStorage = window.Store = function (name) {
        this.name = name;
        var store = this.localStorage().getItem(this.name);
        this.records = store && store.split(",") || []
    }, _.extend(Backbone.LocalStorage.prototype, {
        save: function () {
            this.localStorage().setItem(this.name, this.records.join(","))
        },
        create: function (model) {
            return model.id || (model.id = guid(), model.set(model.idAttribute, model.id)), this.localStorage().setItem(this.name + "-" + model.id, JSON.stringify(model)), this.records.push(model.id.toString()), this.save(), this.find(model)
        },
        update: function (model) {
            return this.localStorage().setItem(this.name + "-" + model.id, JSON.stringify(model)), _.include(this.records, model.id.toString()) || this.records.push(model.id.toString()), this.save(), this.find(model)
        },
        find: function (model) {
            return this.jsonData(this.localStorage().getItem(this.name + "-" + model.id))
        },
        findAll: function () {
            return _(this.records).chain().map(function (id) {
                return this.jsonData(this.localStorage().getItem(this.name + "-" + id))
            }, this).compact().value()
        },
        destroy: function (model) {
            return model.isNew() ? !1 : (this.localStorage().removeItem(this.name + "-" + model.id), this.records = _.reject(this.records, function (id) {
                return id === model.id.toString()
            }), this.save(), model)
        },
        localStorage: function () {
            return localStorage
        },
        jsonData: function (data) {
            return data && JSON.parse(data)
        },
        _clear: function () {
            var local = this.localStorage(),
                itemRe = new RegExp("^" + this.name + "-");
            local.removeItem(this.name), _.chain(local).keys().filter(function (k) {
                return itemRe.test(k)
            }).each(function (k) {
                local.removeItem(k)
            })
        },
        _storageSize: function () {
            return this.localStorage().length
        }
    }), Backbone.LocalStorage.sync = window.Store.sync = Backbone.localSync = function (method, model, options) {
        var resp, errorMessage, store = model.localStorage || model.collection.localStorage,
            syncDfd = $.Deferred && $.Deferred();
        try {
            switch (method) {
            case "read":
                resp = void 0 != model.id ? store.find(model) : store.findAll();
                break;
            case "create":
                resp = store.create(model);
                break;
            case "update":
                resp = store.update(model);
                break;
            case "delete":
                resp = store.destroy(model)
            }
        } catch (error) {
            errorMessage = error.code === DOMException.QUOTA_EXCEEDED_ERR && 0 === store._storageSize() ? "Private browsing is unsupported" : error.message
        }
        return resp ? (model.trigger("sync", model, resp, options), options && options.success && ("0.9.10" === Backbone.VERSION ? options.success(model, resp, options) : options.success(resp)), syncDfd && syncDfd.resolve(resp)) : (errorMessage = errorMessage ? errorMessage : "Record Not Found", model.trigger("error", model, errorMessage, options), options && options.error && ("0.9.10" === Backbone.VERSION ? options.error(model, errorMessage, options) : options.error(errorMessage)), syncDfd && syncDfd.reject(errorMessage)), options && options.complete && options.complete(resp), syncDfd && syncDfd.promise()
    }, Backbone.ajaxSync = Backbone.sync, Backbone.getSyncMethod = function (model) {
        return model.localStorage || model.collection && model.collection.localStorage ? Backbone.localSync : Backbone.ajaxSync
    }, Backbone.sync = function (method, model, options) {
        return Backbone.getSyncMethod(model).apply(this, [method, model, options])
    }, Backbone.LocalStorage
}),
function (root, factory) {
    "object" == typeof exports ? module.exports = factory(require("underscore"), require("backbone")) : "function" == typeof define && define.amd ? define(["underscore", "backbone"], function (_, Backbone) {
        return factory(_ || root._, Backbone || root.Backbone)
    }) : factory(_, Backbone)
}(this, function (_, Backbone) {
    function S4() {
        return (0 | 65536 * (1 + Math.random())).toString(16).substring(1)
    }

    function guid() {
        return S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()
    }
    return Backbone.AsyncStorage = function (name, storage) {
        this.name = name, this.storage = storage || window.asyncStorage, this.records = null, this.call_queue = [];
        var self = this;
        this.asyncStorage().getItem(this.name, function (store) {
            self.records = store && store.split(",") || [], _.each(self.call_queue, function (args) {
                Backbone.AsyncStorage.sync.apply(self, args)
            })
        })
    }, _.extend(Backbone.AsyncStorage.prototype, {
        isReady: function () {
            return null !== this.records
        },
        queue: function (method, model, options) {
            this.call_queue.push([method, model, options])
        },
        save: function (callback) {
            this.asyncStorage().setItem(this.name, this.records.join(","), callback)
        },
        create: function (model, callback) {
            model.id || (model.id = guid(), model.set(model.idAttribute, model.id));
            var self = this;
            this.asyncStorage().setItem(this.name + "-" + model.id, JSON.stringify(model), function () {
                self.records.push(model.id.toString()), self.save(function () {
                    self.find(model, callback)
                })
            })
        },
        update: function (model, callback) {
            var self = this;
            this.asyncStorage().setItem(this.name + "-" + model.id, JSON.stringify(model), function () {
                _.include(self.records, model.id.toString()) ? self.find(model, callback) : (self.records.push(model.id.toString()), self.save(function () {
                    self.find(model, callback)
                }))
            })
        },
        find: function (model, callback) {
            var self = this;
            this.asyncStorage().getItem(this.name + "-" + model.id, function (item) {
                callback(self.jsonData(item))
            })
        },
        findAll: function (callback) {
            var self = this,
                ids = _(this.records).map(function (id) {
                    return self.name + "-" + id
                });
            this.asyncStorage().getItems(ids, function (items) {
                var models = [];
                for (var key in items) items.hasOwnProperty(key) && models.push(self.jsonData(items[key]));
                callback(_.compact(models))
            })
        },
        destroy: function (model, callback) {
            if (model.isNew()) return callback(!1), void 0;
            var self = this;
            this.asyncStorage().removeItem(this.name + "-" + model.id, function () {
                self.records = _.reject(self.records, function (id) {
                    return id === model.id.toString()
                }), self.save(function () {
                    callback(model)
                })
            })
        },
        asyncStorage: function () {
            return this.storage
        },
        jsonData: function (data) {
            return data && JSON.parse(data)
        },
        _clear: function (callback) {
            var name = this.name,
                local = this.asyncStorage();
            local.removeItem(name, function () {
                local.removeItemsWithKeysLike("^" + name + "-", callback)
            })
        },
        _storageSize: function (callback) {
            this.asyncStorage().length(callback)
        }
    }), Backbone.AsyncStorage.sync = function (method, model, options) {
        var store = model.asyncStorage || model.collection.asyncStorage,
            syncDfd = options.syncDfd || Backbone.$ && Backbone.$.Deferred && Backbone.$.Deferred();
        if (!store.isReady()) return options.syncDfd = syncDfd, store.queue(method, model, options), syncDfd && syncDfd.promise();
        var onComplete = function (resp) {
                options && options.complete && options.complete(resp)
            },
            onResponse = function (resp) {
                options && options.success && ("0.9.10" === Backbone.VERSION ? options.success(model, resp, options) : options.success(resp)), syncDfd && syncDfd.resolve(resp), onComplete(resp)
            },
            onError = function (errorMessage) {
                errorMessage = errorMessage || "Record Not Found", options && options.error && ("0.9.10" === Backbone.VERSION ? options.error(model, errorMessage, options) : options.error(errorMessage)), syncDfd && syncDfd.reject(errorMessage), onComplete(null)
            };
        try {
            switch (method) {
            case "read":
                void 0 != model.id ? store.find(model, onResponse) : store.findAll(onResponse);
                break;
            case "create":
                store.create(model, onResponse);
                break;
            case "update":
                if (model.hasChanged("id")) {
                    var clone = new model.constructor;
                    clone.id = model.previous("id"), store.destroy(clone, function () {
                        store.update(model, onResponse)
                    })
                } else store.update(model, onResponse);
                break;
            case "delete":
                store.destroy(model, onResponse)
            }
        } catch (error) {
            onError(error.message)
        }
        return syncDfd && syncDfd.promise()
    }, Backbone.ajaxSync || (Backbone.ajaxSync = Backbone.sync), Backbone.getSyncMethod = function (model) {
        return model.asyncStorage || model.collection && model.collection.asyncStorage ? Backbone.AsyncStorage.sync : Backbone.LocalStorage && (model.localStorage || model.collection && model.collection.localStorage) ? Backbone.LocalStorage.sync : Backbone.ajaxSync
    }, Backbone.sync = function (method, model, options) {
        return Backbone.getSyncMethod(model).apply(this, [method, model, options])
    }, Backbone.AsyncStorage
}), ! function (t, e, i) {
    function a(t, i) {
        var r, o = e.createElement(t || "div");
        for (r in i) o[r] = i[r];
        return o
    }

    function s(t) {
        for (var e = 1, i = arguments.length; i > e; e++) t.appendChild(arguments[e]);
        return t
    }

    function l(t, e, i, o) {
        var a = ["opacity", e, ~~ (100 * t), i, o].join("-"),
            s = .01 + 100 * (i / o),
            l = Math.max(1 - (1 - t) / e * (100 - s), t),
            p = n.substring(0, n.indexOf("Animation")).toLowerCase(),
            u = p && "-" + p + "-" || "";
        return r[a] || (f.insertRule("@" + u + "keyframes " + a + "{0%{opacity:" + l + "}" + s + "%{opacity:" + t + "}" + (s + .01) + "%{opacity:1}" + (s + e) % 100 + "%{opacity:" + t + "}100%{opacity:" + l + "}}", f.cssRules.length), r[a] = 1), a
    }

    function p(t, e) {
        var n, a, r = t.style;
        if (r[e] !== i) return e;
        for (e = e.charAt(0).toUpperCase() + e.slice(1), a = 0; a < o.length; a++)
            if (n = o[a] + e, r[n] !== i) return n
    }

    function u(t, e) {
        for (var i in e) t.style[p(t, i) || i] = e[i];
        return t
    }

    function c(t) {
        for (var e = 1; e < arguments.length; e++) {
            var o = arguments[e];
            for (var r in o) t[r] === i && (t[r] = o[r])
        }
        return t
    }

    function d(t) {
        for (var e = {
            x: t.offsetLeft,
            y: t.offsetTop
        }; t = t.offsetParent;) e.x += t.offsetLeft, e.y += t.offsetTop;
        return e
    }

    function m(t) {
        return this.spin ? (this.opts = c(t || {}, m.defaults, h), void 0) : new m(t)
    }
    var n, o = ["webkit", "Moz", "ms", "O"],
        r = {},
        f = function () {
            var t = a("style", {
                type: "text/css"
            });
            return s(e.getElementsByTagName("head")[0], t), t.sheet || t.styleSheet
        }(),
        h = {
            lines: 12,
            length: 7,
            width: 5,
            radius: 10,
            rotate: 0,
            corners: 1,
            color: "#000",
            speed: 1,
            trail: 100,
            opacity: .25,
            fps: 20,
            zIndex: 2e9,
            className: "spinner",
            top: "auto",
            left: "auto",
            position: "relative"
        };
    m.defaults = {}, c(m.prototype, {
        spin: function (t) {
            this.stop();
            var s, f, e = this,
                i = e.opts,
                o = e.el = u(a(0, {
                    className: i.className
                }), {
                    position: i.position,
                    width: 0,
                    zIndex: i.zIndex
                }),
                r = i.radius + i.length + i.width;
            if (t && (t.insertBefore(o, t.firstChild || null), f = d(t), s = d(o), u(o, {
                left: ("auto" == i.left ? f.x - s.x + (t.offsetWidth >> 1) : parseInt(i.left, 10) + r) + "px",
                top: ("auto" == i.top ? f.y - s.y + (t.offsetHeight >> 1) : parseInt(i.top, 10) + r) + "px"
            })), o.setAttribute("aria-role", "progressbar"), e.lines(o, e.opts), !n) {
                var l = 0,
                    p = i.fps,
                    c = p / i.speed,
                    h = (1 - i.opacity) / (c * i.trail / 100),
                    m = c / i.lines;
                ! function y() {
                    l++;
                    for (var t = i.lines; t; t--) {
                        var r = Math.max(1 - (l + t * m) % c * h, i.opacity);
                        e.opacity(o, i.lines - t, r, i)
                    }
                    e.timeout = e.el && setTimeout(y, ~~ (1e3 / p))
                }()
            }
            return e
        },
        stop: function () {
            var t = this.el;
            return t && (clearTimeout(this.timeout), t.parentNode && t.parentNode.removeChild(t), this.el = i), this
        },
        lines: function (t, e) {
            function r(t, o) {
                return u(a(), {
                    position: "absolute",
                    width: e.length + e.width + "px",
                    height: e.width + "px",
                    background: t,
                    boxShadow: o,
                    transformOrigin: "left",
                    transform: "rotate(" + ~~(360 / e.lines * i + e.rotate) + "deg) translate(" + e.radius + "px,0)",
                    borderRadius: (e.corners * e.width >> 1) + "px"
                })
            }
            for (var o, i = 0; i < e.lines; i++) o = u(a(), {
                position: "absolute",
                top: 1 + ~(e.width / 2) + "px",
                transform: e.hwaccel ? "translate3d(0,0,0)" : "",
                opacity: e.opacity,
                animation: n && l(e.opacity, e.trail, i, e.lines) + " " + 1 / e.speed + "s linear infinite"
            }), e.shadow && s(o, u(r("#000", "0 0 4px #000"), {
                top: "2px"
            })), s(t, s(o, r(e.color, "0 0 1px rgba(0,0,0,.1)")));
            return t
        },
        opacity: function (t, e, i) {
            e < t.childNodes.length && (t.childNodes[e].style.opacity = i)
        }
    }),
    function () {
        function t(t, e) {
            return a("<" + t + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', e)
        }
        var e = u(a("group"), {
            behavior: "url(#default#VML)"
        });
        !p(e, "transform") && e.adj ? (f.addRule(".spin-vml", "behavior:url(#default#VML)"), m.prototype.lines = function (e, i) {
            function n() {
                return u(t("group", {
                    coordsize: r + " " + r,
                    coordorigin: -o + " " + -o
                }), {
                    width: r,
                    height: r
                })
            }

            function p(e, r, a) {
                s(f, s(u(n(), {
                    rotation: 360 / i.lines * e + "deg",
                    left: ~~r
                }), s(u(t("roundrect", {
                    arcsize: i.corners
                }), {
                    width: o,
                    height: i.width,
                    left: i.radius,
                    top: -i.width >> 1,
                    filter: a
                }), t("fill", {
                    color: i.color,
                    opacity: i.opacity
                }), t("stroke", {
                    opacity: 0
                }))))
            }
            var l, o = i.length + i.width,
                r = 2 * o,
                a = 2 * -(i.width + i.length) + "px",
                f = u(n(), {
                    position: "absolute",
                    top: a,
                    left: a
                });
            if (i.shadow)
                for (l = 1; l <= i.lines; l++) p(l, -2, "progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)");
            for (l = 1; l <= i.lines; l++) p(l);
            return s(e, f)
        }, m.prototype.opacity = function (t, e, i, o) {
            var r = t.firstChild;
            o = o.shadow && o.lines || 0, r && e + o < r.childNodes.length && (r = r.childNodes[e + o], r = r && r.firstChild, r = r && r.firstChild, r && (r.opacity = i))
        }) : n = p(e, "animation")
    }(), "function" == typeof define && define.amd ? define(function () {
        return m
    }) : t.Spinner = m
}(window, document),
function (factory) {
    "function" == typeof define && define.amd ? define(["jquery"], factory) : factory(jQuery)
}(function ($) {
    function raw(s) {
        return s
    }

    function decoded(s) {
        return decodeURIComponent(s.replace(pluses, " "))
    }

    function converted(s) {
        0 === s.indexOf('"') && (s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, "\\"));
        try {
            return config.json ? JSON.parse(s) : s
        } catch (er) {}
    }
    var pluses = /\+/g,
        config = $.cookie = function (key, value, options) {
            if (void 0 !== value) {
                if (options = $.extend({}, config.defaults, options), "number" == typeof options.expires) {
                    var days = options.expires,
                        t = options.expires = new Date;
                    t.setDate(t.getDate() + days)
                }
                return value = config.json ? JSON.stringify(value) : String(value), document.cookie = [config.raw ? key : encodeURIComponent(key), "=", config.raw ? value : encodeURIComponent(value), options.expires ? "; expires=" + options.expires.toUTCString() : "", options.path ? "; path=" + options.path : "", options.domain ? "; domain=" + options.domain : "", options.secure ? "; secure" : ""].join("")
            }
            for (var decode = config.raw ? raw : decoded, cookies = document.cookie.split("; "), result = key ? void 0 : {}, i = 0, l = cookies.length; l > i; i++) {
                var parts = cookies[i].split("="),
                    name = decode(parts.shift()),
                    cookie = decode(parts.join("="));
                if (key && key === name) {
                    result = converted(cookie);
                    break
                }
                key || (result[name] = converted(cookie))
            }
            return result
        };
    config.defaults = {}, $.removeCookie = function (key, options) {
        return void 0 !== $.cookie(key) ? ($.cookie(key, "", $.extend(options, {
            expires: -1
        })), !0) : !1
    }
}), ! function (a) {
    "function" == typeof define && define.amd ? define(["jquery"], a) : a(jQuery)
}(function (a) {
    function b(a) {
        if (a.minTime && (a.minTime = t(a.minTime)), a.maxTime && (a.maxTime = t(a.maxTime)), a.durationTime && "function" != typeof a.durationTime && (a.durationTime = t(a.durationTime)), a.disableTimeRanges.length > 0) {
            for (var b in a.disableTimeRanges) a.disableTimeRanges[b] = [t(a.disableTimeRanges[b][0]), t(a.disableTimeRanges[b][1])];
            a.disableTimeRanges = a.disableTimeRanges.sort(function (a, b) {
                return a[0] - b[0]
            })
        }
        return a
    }

    function c(b) {
        return label = b.label, className = b.className, value = b.value, a("<li />", {
            "class": className,
            text: label
        }).data("time", value)
    }

    function d(b) {
        var d = b.data("timepicker-settings"),
            e = b.data("timepicker-list");
        e && e.length && (e.remove(), b.data("timepicker-list", !1)), e = a("<ul />", {
            "class": "ui-timepicker-list"
        });
        var f = a("<div />", {
            "class": "ui-timepicker-wrapper",
            tabindex: -1
        });
        f.css({
            display: "none",
            position: "absolute"
        }).append(e), d.className && f.addClass(d.className), null === d.minTime && null === d.durationTime || !d.showDuration || f.addClass("ui-timepicker-with-duration");
        var g = d.minTime;
        "function" == typeof d.durationTime ? g = t(d.durationTime()) : null !== d.durationTime && (g = d.durationTime);
        var i = null !== d.minTime ? d.minTime : 0,
            k = null !== d.maxTime ? d.maxTime : i + w - 1;
        i >= k && (k += w);
        for (var l = d.disableTimeRanges, m = 0, n = l.length, o = i; k >= o; o += 60 * d.step) {
            var p = o % w,
                u = a("<li />");
            if (u.data("time", p), u.text(s(p, d.timeFormat)), (null !== d.minTime || null !== d.durationTime) && d.showDuration) {
                var v = a("<span />");
                v.addClass("ui-timepicker-duration"), v.text(" (" + r(o - g) + ")"), u.append(v)
            }
            n > m && (p >= l[m][1] && (m += 1), l[m] && p >= l[m][0] && p < l[m][1] && u.addClass("ui-timepicker-disabled")), e.append(u)
        }
        if (d.endOption && Object(d.endOption) === d.endOption) {
            var x = c(d.endOption, d.useSelect);
            e.append(x)
        }
        f.data("timepicker-input", b), b.data("timepicker-list", f);
        var y = d.appendTo;
        "string" == typeof y ? y = a(y) : "function" == typeof y && (y = y(b)), y.append(f), j(b, e), e.on("click", "li", function () {
            b.off("focus.timepicker"), b.on("focus.timepicker-ie-hack", function () {
                b.off("focus.timepicker-ie-hack"), b.on("focus.timepicker", z.show)
            }), h(b) || b[0].focus(), e.find("li").removeClass("ui-timepicker-selected"), a(this).addClass("ui-timepicker-selected"), q(b) && (b.trigger("hideTimepicker"), f.hide())
        })
    }

    function e() {
        return new Date(1970, 1, 1, 0, 0, 0)
    }

    function f(b) {
        "ontouchstart" in document ? a("body").on("touchstart.ui-timepicker", g) : (a("body").on("mousedown.ui-timepicker", g), b.closeOnWindowScroll && a(window).on("scroll.ui-timepicker", g))
    }

    function g(b) {
        var c = a(b.target),
            d = c.closest(".ui-timepicker-input");
        0 === d.length && 0 === c.closest(".ui-timepicker-wrapper").length && (z.hide(), a("body").unbind(".ui-timepicker"), a(window).unbind(".ui-timepicker"))
    }

    function h(a) {
        var b = a.data("timepicker-settings");
        return (window.navigator.msMaxTouchPoints || "ontouchstart" in document) && b.disableTouchKeyboard
    }

    function i(b, c, d) {
        if (!d && 0 !== d) return !1;
        var e = b.data("timepicker-settings"),
            f = !1,
            g = 30 * e.step;
        return c.find("li").each(function (b, c) {
            var e = a(c),
                h = e.data("time") - d;
            return Math.abs(h) < g || h == g ? (f = e, !1) : void 0
        }), f
    }

    function j(a, b) {
        b.find("li").removeClass("ui-timepicker-selected");
        var c = t(l(a));
        if (c) {
            var d = i(a, b, c);
            if (d) {
                var e = d.offset().top - b.offset().top;
                (e + d.outerHeight() > b.outerHeight() || 0 > e) && b.scrollTop(b.scrollTop() + d.position().top - d.outerHeight()), d.addClass("ui-timepicker-selected")
            }
        }
    }

    function k() {
        if ("" !== this.value) {
            var b = a(this),
                c = b.data("timepicker-list");
            if (!c || !c.is(":visible")) {
                var d = t(this.value);
                if (null === d) return void b.trigger("timeFormatError");
                var e = b.data("timepicker-settings"),
                    f = !1;
                if (null !== e.minTime && d < e.minTime ? f = !0 : null !== e.maxTime && d > e.maxTime && (f = !0), a.each(e.disableTimeRanges, function () {
                    return d >= this[0] && d < this[1] ? (f = !0, !1) : void 0
                }), e.forceRoundTime) {
                    var g = d % (60 * e.step);
                    g >= 30 * e.step ? d += 60 * e.step - g : d -= g
                }
                var h = s(d, e.timeFormat);
                f ? m(b, h, "error") && b.trigger("timeRangeError") : m(b, h)
            }
        }
    }

    function l(a) {
        return a.is("input") ? a.val() : a.data("ui-timepicker-value")
    }

    function m(a, b, c) {
        return a.val() != b ? (a.is("input") ? a.val(b) : a.data("ui-timepicker-value", b), "select" == c ? a.trigger("selectTime").trigger("changeTime").trigger("change") : "error" != c && a.trigger("changeTime"), !0) : (a.trigger("selectTime"), !1)
    }

    function n(b) {
        var c = a(this),
            d = c.data("timepicker-list");
        if (!d || !d.is(":visible")) {
            if (40 != b.keyCode) return o(b, c);
            h(c) || c.focus()
        }
        switch (b.keyCode) {
        case 13:
            return q(c) && z.hide.apply(this), b.preventDefault(), !1;
        case 38:
            var e = d.find(".ui-timepicker-selected");
            return e.length ? e.is(":first-child") || (e.removeClass("ui-timepicker-selected"), e.prev().addClass("ui-timepicker-selected"), e.prev().position().top < e.outerHeight() && d.scrollTop(d.scrollTop() - e.outerHeight())) : (d.find("li").each(function (b, c) {
                return a(c).position().top > 0 ? (e = a(c), !1) : void 0
            }), e.addClass("ui-timepicker-selected")), !1;
        case 40:
            return e = d.find(".ui-timepicker-selected"), 0 === e.length ? (d.find("li").each(function (b, c) {
                return a(c).position().top > 0 ? (e = a(c), !1) : void 0
            }), e.addClass("ui-timepicker-selected")) : e.is(":last-child") || (e.removeClass("ui-timepicker-selected"), e.next().addClass("ui-timepicker-selected"), e.next().position().top + 2 * e.outerHeight() > d.outerHeight() && d.scrollTop(d.scrollTop() + e.outerHeight())), !1;
        case 27:
            d.find("li").removeClass("ui-timepicker-selected"), z.hide();
            break;
        case 9:
            z.hide();
            break;
        default:
            return o(b, c)
        }
    }

    function o(a, b) {
        return !b.data("timepicker-settings").disableTextInput || a.ctrlKey || a.altKey || a.metaKey || 2 != a.keyCode && a.keyCode < 46
    }

    function p(b) {
        var c = a(this),
            d = c.data("timepicker-list");
        if (!d || !d.is(":visible")) return !0;
        switch (b.keyCode) {
        case 96:
        case 97:
        case 98:
        case 99:
        case 100:
        case 101:
        case 102:
        case 103:
        case 104:
        case 105:
        case 48:
        case 49:
        case 50:
        case 51:
        case 52:
        case 53:
        case 54:
        case 55:
        case 56:
        case 57:
        case 65:
        case 77:
        case 80:
        case 186:
        case 8:
        case 46:
            j(c, d);
            break;
        default:
            return
        }
    }

    function q(a) {
        var b = a.data("timepicker-settings"),
            c = a.data("timepicker-list"),
            d = null,
            e = "",
            f = c.find(".ui-timepicker-selected");
        return f.hasClass("ui-timepicker-disabled") ? !1 : (f.length ? d = f.data("time") : l(a) && (d = t(l(a)), j(a, c)), null !== d && (e = "string" == typeof d ? d : s(d, b.timeFormat), m(a, e, "select")), !0)
    }

    function r(a) {
        var b, c = Math.round(a / 60);
        if (Math.abs(c) < 60) b = [c, y.mins];
        else if (60 == c) b = ["1", y.hr];
        else {
            var d = (c / 60).toFixed(1);
            "." != y.decimal && (d = d.replace(".", y.decimal)), b = [d, y.hrs]
        }
        return b.join(" ")
    }

    function s(a, b) {
        if (null !== a) {
            for (var c, d, e = new Date(v.valueOf() + 1e3 * a), f = "", g = 0; g < b.length; g++) switch (d = b.charAt(g)) {
            case "a":
                f += e.getHours() > 11 ? "pm" : "am";
                break;
            case "A":
                f += e.getHours() > 11 ? "PM" : "AM";
                break;
            case "g":
                c = e.getHours() % 12, f += 0 === c ? "12" : c;
                break;
            case "G":
                f += e.getHours();
                break;
            case "h":
                c = e.getHours() % 12, 0 !== c && 10 > c && (c = "0" + c), f += 0 === c ? "12" : c;
                break;
            case "H":
                c = e.getHours(), f += c > 9 ? c : "0" + c;
                break;
            case "i":
                var h = e.getMinutes();
                f += h > 9 ? h : "0" + h;
                break;
            case "s":
                a = e.getSeconds(), f += a > 9 ? a : "0" + a;
                break;
            default:
                f += d
            }
            return f
        }
    }

    function t(a) {
        if ("" === a) return null;
        if (!a || a + 0 == a) return a;
        "object" == typeof a && (a = a.getHours() + ":" + u(a.getMinutes()) + ":" + u(a.getSeconds())), a = a.toLowerCase();
        var b;
        if (new Date(0), -1 === a.indexOf(":") ? (b = a.match(/^([0-9]):?([0-5][0-9])?:?([0-5][0-9])?\s*([pa]?)m?$/), b || (b = a.match(/^([0-2][0-9]):?([0-5][0-9])?:?([0-5][0-9])?\s*([pa]?)m?$/))) : b = a.match(/^(\d{1,2})(?::([0-5][0-9]))?(?::([0-5][0-9]))?\s*([pa]?)m?$/), !b) return null;
        var c, d = parseInt(1 * b[1], 10);
        c = b[4] ? 12 == d ? "p" == b[4] ? 12 : 0 : d + ("p" == b[4] ? 12 : 0) : d;
        var e = 1 * b[2] || 0,
            f = 1 * b[3] || 0;
        return 3600 * c + 60 * e + f
    }

    function u(a) {
        return ("0" + a).slice(-2)
    }
    var v = e(),
        w = 86400,
        x = {
            className: null,
            minTime: null,
            maxTime: null,
            durationTime: null,
            step: 30,
            showDuration: !1,
            timeFormat: "g:ia",
            scrollDefaultNow: !1,
            scrollDefaultTime: !1,
            selectOnBlur: !1,
            disableTouchKeyboard: !0,
            forceRoundTime: !1,
            appendTo: "body",
            disableTimeRanges: [],
            closeOnWindowScroll: !1,
            disableTextInput: !1,
            endOption: null
        },
        y = {
            decimal: ".",
            mins: "mins",
            hr: "hr",
            hrs: "hrs"
        },
        z = {
            init: function (c) {
                return this.each(function () {
                    var d = a(this);
                    if ("SELECT" == d[0].tagName) {
                        for (var e = {
                            type: "text",
                            value: d.val()
                        }, f = d[0].attributes, g = 0; g < f.length; g++) e[f[g].nodeName] = f[g].nodeValue;
                        var h = a("<input />", e);
                        d.replaceWith(h), d = h
                    }
                    var i = a.extend({}, x);
                    c && (i = a.extend(i, c)), i.lang && (y = a.extend(y, i.lang)), i = b(i), d.data("timepicker-settings", i), d.prop("autocomplete", "off"), d.on("click.timepicker focus.timepicker", z.show), d.on("change.timepicker", k), d.on("keydown.timepicker", n), d.on("keyup.timepicker", p), d.addClass("ui-timepicker-input"), k.call(d.get(0))
                })
            },
            show: function () {
                var b = a(this),
                    c = b.data("timepicker-settings");
                h(b) && b.blur();
                var e = b.data("timepicker-list");
                if (!b.prop("readonly") && (e && 0 !== e.length && "function" != typeof c.durationTime || (d(b), e = b.data("timepicker-list")), !e.is(":visible"))) {
                    z.hide(), e.show(), e.offset(b.offset().top + b.outerHeight(!0) + e.outerHeight() > a(window).height() + a(window).scrollTop() ? {
                        left: b.offset().left + parseInt(e.css("marginLeft").replace("px", ""), 10),
                        top: b.offset().top - e.outerHeight() + parseInt(e.css("marginTop").replace("px", ""), 10)
                    } : {
                        left: b.offset().left + parseInt(e.css("marginLeft").replace("px", ""), 10),
                        top: b.offset().top + b.outerHeight() + parseInt(e.css("marginTop").replace("px", ""), 10)
                    });
                    var g = e.find(".ui-timepicker-selected");
                    if (g.length || (l(b) ? g = i(b, e, t(l(b))) : c.scrollDefaultNow ? g = i(b, e, t(new Date)) : c.scrollDefaultTime !== !1 && (g = i(b, e, t(c.scrollDefaultTime)))), g && g.length) {
                        var j = e.scrollTop() + g.position().top - g.outerHeight();
                        e.scrollTop(j)
                    } else e.scrollTop(0);
                    f(c), b.trigger("showTimepicker")
                }
            },
            hide: function () {
                a(".ui-timepicker-wrapper:visible").each(function () {
                    var b = a(this),
                        c = b.data("timepicker-input"),
                        d = c.data("timepicker-settings");
                    d && d.selectOnBlur && q(c), b.hide(), c.trigger("hideTimepicker")
                })
            },
            option: function (c, d) {
                var e = this,
                    f = e.data("timepicker-settings"),
                    g = e.data("timepicker-list");
                if ("object" == typeof c) f = a.extend(f, c);
                else if ("string" == typeof c && "undefined" != typeof d) f[c] = d;
                else if ("string" == typeof c) return f[c];
                return f = b(f), e.data("timepicker-settings", f), g && (g.remove(), e.data("timepicker-list", !1)), e
            },
            getSecondsFromMidnight: function () {
                return t(l(this))
            },
            getTime: function () {
                var a = this,
                    b = new Date;
                return b.setHours(0, 0, 0, 0), new Date(b.valueOf() + 1e3 * t(l(a)))
            },
            setTime: function (a) {
                var b = this;
                if ("string" == typeof a) m(b, a);
                else {
                    var c = s(t(a), b.data("timepicker-settings").timeFormat);
                    m(b, c)
                }
            },
            remove: function () {
                var a = this;
                a.hasClass("ui-timepicker-input") && (a.removeAttr("autocomplete", "off"), a.removeClass("ui-timepicker-input"), a.removeData("timepicker-settings"), a.off(".timepicker"), a.data("timepicker-list") && a.data("timepicker-list").remove(), a.removeData("timepicker-list"))
            }
        };
    a.fn.timepicker = function (b) {
        return z[b] ? z[b].apply(this, Array.prototype.slice.call(arguments, 1)) : "object" != typeof b && b ? void a.error("Method " + b + " does not exist on jQuery.timepicker") : z.init.apply(this, arguments)
    }
});
var requirejs, require, define;
! function (Y) {
    function I(b) {
        return "[object Function]" === L.call(b)
    }

    function J(b) {
        return "[object Array]" === L.call(b)
    }

    function x(b, c) {
        if (b) {
            var d;
            for (d = 0; d < b.length && (!b[d] || !c(b[d], d, b)); d += 1);
        }
    }

    function M(b, c) {
        if (b) {
            var d;
            for (d = b.length - 1; d > -1 && (!b[d] || !c(b[d], d, b)); d -= 1);
        }
    }

    function r(b, c) {
        return da.call(b, c)
    }

    function i(b, c) {
        return r(b, c) && b[c]
    }

    function E(b, c) {
        for (var d in b)
            if (r(b, d) && c(b[d], d)) break
    }

    function Q(b, c, d, i) {
        return c && E(c, function (c, h) {
            (d || !r(b, h)) && (i && "string" != typeof c ? (b[h] || (b[h] = {}), Q(b[h], c, d, i)) : b[h] = c)
        }), b
    }

    function t(b, c) {
        return function () {
            return c.apply(b, arguments)
        }
    }

    function Z(b) {
        if (!b) return b;
        var c = Y;
        return x(b.split("."), function (b) {
            c = c[b]
        }), c
    }

    function F(b, c, d, i) {
        return c = Error(c + "\nhttp://requirejs.org/docs/errors.html#" + b), c.requireType = b, c.requireModules = i, d && (c.originalError = d), c
    }

    function ea(b) {
        function c(a, f, v) {
            var e, n, b, c, d, k, g, h = f && f.split("/");
            e = h;
            var l = m.map,
                j = l && l["*"];
            if (a && "." === a.charAt(0))
                if (f) {
                    for (e = i(m.pkgs, f) ? h = [f] : h.slice(0, h.length - 1), f = a = e.concat(a.split("/")), e = 0; f[e]; e += 1)
                        if (n = f[e], "." === n) f.splice(e, 1), e -= 1;
                        else if (".." === n) {
                        if (1 === e && (".." === f[2] || ".." === f[0])) break;
                        e > 0 && (f.splice(e - 1, 2), e -= 2)
                    }
                    e = i(m.pkgs, f = a[0]), a = a.join("/"), e && a === f + "/" + e.main && (a = f)
                } else 0 === a.indexOf("./") && (a = a.substring(2));
            if (v && (h || j) && l) {
                for (f = a.split("/"), e = f.length; e > 0; e -= 1) {
                    if (b = f.slice(0, e).join("/"), h)
                        for (n = h.length; n > 0; n -= 1)
                            if ((v = i(l, h.slice(0, n).join("/"))) && (v = i(v, b))) {
                                c = v, d = e;
                                break
                            }
                    if (c) break;
                    !k && j && i(j, b) && (k = i(j, b), g = e)
                }!c && k && (c = k, d = g), c && (f.splice(0, d, c), a = f.join("/"))
            }
            return a
        }

        function d(a) {
            z && x(document.getElementsByTagName("script"), function (f) {
                return f.getAttribute("data-requiremodule") === a && f.getAttribute("data-requirecontext") === k.contextName ? (f.parentNode.removeChild(f), !0) : void 0
            })
        }

        function y(a) {
            var f = i(m.paths, a);
            return f && J(f) && 1 < f.length ? (d(a), f.shift(), k.require.undef(a), k.require([a]), !0) : void 0
        }

        function g(a) {
            var f, b = a ? a.indexOf("!") : -1;
            return b > -1 && (f = a.substring(0, b), a = a.substring(b + 1, a.length)), [f, a]
        }

        function h(a, f, b, e) {
            var n, u, d = null,
                h = f ? f.name : null,
                l = a,
                m = !0,
                j = "";
            return a || (m = !1, a = "_@r" + (L += 1)), a = g(a), d = a[0], a = a[1], d && (d = c(d, h, e), u = i(p, d)), a && (d ? j = u && u.normalize ? u.normalize(a, function (a) {
                return c(a, h, e)
            }) : c(a, h, e) : (j = c(a, h, e), a = g(j), d = a[0], j = a[1], b = !0, n = k.nameToUrl(j))), b = !d || u || b ? "" : "_unnormalized" + (M += 1), {
                prefix: d,
                name: j,
                parentMap: f,
                unnormalized: !!b,
                url: n,
                originalName: l,
                isDefine: m,
                id: (d ? d + "!" + j : j) + b
            }
        }

        function q(a) {
            var f = a.id,
                b = i(j, f);
            return b || (b = j[f] = new k.Module(a)), b
        }

        function s(a, f, b) {
            var e = a.id,
                n = i(j, e);
            !r(p, e) || n && !n.defineEmitComplete ? q(a).on(f, b) : "defined" === f && b(p[e])
        }

        function A(a, f) {
            var b = a.requireModules,
                e = !1;
            f ? f(a) : (x(b, function (f) {
                (f = i(j, f)) && (f.error = a, f.events.error && (e = !0, f.emit("error", a)))
            }), e || l.onError(a))
        }

        function w() {
            R.length && (fa.apply(G, [G.length - 1, 0].concat(R)), R = [])
        }

        function B(a, f, b) {
            var e = a.map.id;
            a.error ? a.emit("error", a.error) : (f[e] = !0, x(a.depMaps, function (e, c) {
                var d = e.id,
                    h = i(j, d);
                h && !a.depMatched[c] && !b[d] && (i(f, d) ? (a.defineDep(c, p[d]), a.check()) : B(h, f, b))
            }), b[e] = !0)
        }

        function C() {
            var a, f, b, e, n = (b = 1e3 * m.waitSeconds) && k.startTime + b < (new Date).getTime(),
                c = [],
                h = [],
                g = !1,
                l = !0;
            if (!T) {
                if (T = !0, E(j, function (b) {
                    if (a = b.map, f = a.id, b.enabled && (a.isDefine || h.push(b), !b.error))
                        if (!b.inited && n) y(f) ? g = e = !0 : (c.push(f), d(f));
                        else if (!b.inited && b.fetched && a.isDefine && (g = !0, !a.prefix)) return l = !1
                }), n && c.length) return b = F("timeout", "Load timeout for modules: " + c, null, c), b.contextName = k.contextName, A(b);
                l && x(h, function (a) {
                    B(a, {}, {})
                }), n && !e || !g || !z && !$ || U || (U = setTimeout(function () {
                    U = 0, C()
                }, 50)), T = !1
            }
        }

        function D(a) {
            r(p, a[0]) || q(h(a[0], null, !0)).init(a[1], a[2])
        }

        function H(a) {
            var a = a.currentTarget || a.srcElement,
                b = k.onScriptLoad;
            return a.detachEvent && !V ? a.detachEvent("onreadystatechange", b) : a.removeEventListener("load", b, !1), b = k.onScriptError, (!a.detachEvent || V) && a.removeEventListener("error", b, !1), {
                node: a,
                id: a && a.getAttribute("data-requiremodule")
            }
        }

        function K() {
            var a;
            for (w(); G.length;) {
                if (a = G.shift(), null === a[0]) return A(F("mismatch", "Mismatched anonymous define() module: " + a[a.length - 1]));
                D(a)
            }
        }
        var T, W, k, N, U, m = {
                waitSeconds: 7,
                baseUrl: "./",
                paths: {},
                pkgs: {},
                shim: {},
                map: {},
                config: {}
            },
            j = {},
            X = {},
            G = [],
            p = {},
            S = {},
            L = 1,
            M = 1;
        return N = {
            require: function (a) {
                return a.require ? a.require : a.require = k.makeRequire(a.map)
            },
            exports: function (a) {
                return a.usingExports = !0, a.map.isDefine ? a.exports ? a.exports : a.exports = p[a.map.id] = {} : void 0
            },
            module: function (a) {
                return a.module ? a.module : a.module = {
                    id: a.map.id,
                    uri: a.map.url,
                    config: function () {
                        return m.config && i(m.config, a.map.id) || {}
                    },
                    exports: p[a.map.id]
                }
            }
        }, W = function (a) {
            this.events = i(X, a.id) || {}, this.map = a, this.shim = i(m.shim, a.id), this.depExports = [], this.depMaps = [], this.depMatched = [], this.pluginMaps = {}, this.depCount = 0
        }, W.prototype = {
            init: function (a, b, c, e) {
                e = e || {}, this.inited || (this.factory = b, c ? this.on("error", c) : this.events.error && (c = t(this, function (a) {
                    this.emit("error", a)
                })), this.depMaps = a && a.slice(0), this.errback = c, this.inited = !0, this.ignore = e.ignore, e.enabled || this.enabled ? this.enable() : this.check())
            },
            defineDep: function (a, b) {
                this.depMatched[a] || (this.depMatched[a] = !0, this.depCount -= 1, this.depExports[a] = b)
            },
            fetch: function () {
                if (!this.fetched) {
                    this.fetched = !0, k.startTime = (new Date).getTime();
                    var a = this.map;
                    if (!this.shim) return a.prefix ? this.callPlugin() : this.load();
                    k.makeRequire(this.map, {
                        enableBuildCallback: !0
                    })(this.shim.deps || [], t(this, function () {
                        return a.prefix ? this.callPlugin() : this.load()
                    }))
                }
            },
            load: function () {
                var a = this.map.url;
                S[a] || (S[a] = !0, k.load(this.map.id, a))
            },
            check: function () {
                if (this.enabled && !this.enabling) {
                    var a, b, c = this.map.id;
                    b = this.depExports;
                    var e = this.exports,
                        n = this.factory;
                    if (this.inited) {
                        if (this.error) this.emit("error", this.error);
                        else if (!this.defining) {
                            if (this.defining = !0, 1 > this.depCount && !this.defined) {
                                if (I(n)) {
                                    if (this.events.error) try {
                                        e = k.execCb(c, n, b, e)
                                    } catch (d) {
                                        a = d
                                    } else e = k.execCb(c, n, b, e);
                                    if (this.map.isDefine && ((b = this.module) && void 0 !== b.exports && b.exports !== this.exports ? e = b.exports : void 0 === e && this.usingExports && (e = this.exports)), a) return a.requireMap = this.map, a.requireModules = [this.map.id], a.requireType = "define", A(this.error = a)
                                } else e = n;
                                this.exports = e, this.map.isDefine && !this.ignore && (p[c] = e, l.onResourceLoad) && l.onResourceLoad(k, this.map, this.depMaps), delete j[c], this.defined = !0
                            }
                            this.defining = !1, this.defined && !this.defineEmitted && (this.defineEmitted = !0, this.emit("defined", this.exports), this.defineEmitComplete = !0)
                        }
                    } else this.fetch()
                }
            },
            callPlugin: function () {
                var a = this.map,
                    b = a.id,
                    d = h(a.prefix);
                this.depMaps.push(d), s(d, "defined", t(this, function (e) {
                    var n, d;
                    d = this.map.name;
                    var v = this.map.parentMap ? this.map.parentMap.name : null,
                        g = k.makeRequire(a.parentMap, {
                            enableBuildCallback: !0
                        });
                    this.map.unnormalized ? (e.normalize && (d = e.normalize(d, function (a) {
                        return c(a, v, !0)
                    }) || ""), e = h(a.prefix + "!" + d, this.map.parentMap), s(e, "defined", t(this, function (a) {
                        this.init([], function () {
                            return a
                        }, null, {
                            enabled: !0,
                            ignore: !0
                        })
                    })), (d = i(j, e.id)) && (this.depMaps.push(e), this.events.error && d.on("error", t(this, function (a) {
                        this.emit("error", a)
                    })), d.enable())) : (n = t(this, function (a) {
                        this.init([], function () {
                            return a
                        }, null, {
                            enabled: !0
                        })
                    }), n.error = t(this, function (a) {
                        this.inited = !0, this.error = a, a.requireModules = [b], E(j, function (a) {
                            0 === a.map.id.indexOf(b + "_unnormalized") && delete j[a.map.id]
                        }), A(a)
                    }), n.fromText = t(this, function (e, c) {
                        var d = a.name,
                            u = h(d),
                            v = O;
                        c && (e = c), v && (O = !1), q(u), r(m.config, b) && (m.config[d] = m.config[b]);
                        try {
                            l.exec(e)
                        } catch (j) {
                            return A(F("fromtexteval", "fromText eval for " + b + " failed: " + j, j, [b]))
                        }
                        v && (O = !0), this.depMaps.push(u), k.completeLoad(d), g([d], n)
                    }), e.load(a.name, g, n, m))
                })), k.enable(d, this), this.pluginMaps[d.id] = d
            },
            enable: function () {
                this.enabling = this.enabled = !0, x(this.depMaps, t(this, function (a, b) {
                    var c, e;
                    if ("string" == typeof a) {
                        if (a = h(a, this.map.isDefine ? this.map : this.map.parentMap, !1, !this.skipMap), this.depMaps[b] = a, c = i(N, a.id)) return this.depExports[b] = c(this), void 0;
                        this.depCount += 1, s(a, "defined", t(this, function (a) {
                            this.defineDep(b, a), this.check()
                        })), this.errback && s(a, "error", this.errback)
                    }
                    c = a.id, e = j[c], !r(N, c) && e && !e.enabled && k.enable(a, this)
                })), E(this.pluginMaps, t(this, function (a) {
                    var b = i(j, a.id);
                    b && !b.enabled && k.enable(a, this)
                })), this.enabling = !1, this.check()
            },
            on: function (a, b) {
                var c = this.events[a];
                c || (c = this.events[a] = []), c.push(b)
            },
            emit: function (a, b) {
                x(this.events[a], function (a) {
                    a(b)
                }), "error" === a && delete this.events[a]
            }
        }, k = {
            config: m,
            contextName: b,
            registry: j,
            defined: p,
            urlFetched: S,
            defQueue: G,
            Module: W,
            makeModuleMap: h,
            nextTick: l.nextTick,
            configure: function (a) {
                a.baseUrl && "/" !== a.baseUrl.charAt(a.baseUrl.length - 1) && (a.baseUrl += "/");
                var b = m.pkgs,
                    c = m.shim,
                    e = {
                        paths: !0,
                        config: !0,
                        map: !0
                    };
                E(a, function (a, b) {
                    e[b] ? "map" === b ? Q(m[b], a, !0, !0) : Q(m[b], a, !0) : m[b] = a
                }), a.shim && (E(a.shim, function (a, b) {
                    J(a) && (a = {
                        deps: a
                    }), !a.exports && !a.init || a.exportsFn || (a.exportsFn = k.makeShimExports(a)), c[b] = a
                }), m.shim = c), a.packages && (x(a.packages, function (a) {
                    a = "string" == typeof a ? {
                        name: a
                    } : a, b[a.name] = {
                        name: a.name,
                        location: a.location || a.name,
                        main: (a.main || "main").replace(ga, "").replace(aa, "")
                    }
                }), m.pkgs = b), E(j, function (a, b) {
                    !a.inited && !a.map.unnormalized && (a.map = h(b))
                }), (a.deps || a.callback) && k.require(a.deps || [], a.callback)
            },
            makeShimExports: function (a) {
                return function () {
                    var b;
                    return a.init && (b = a.init.apply(Y, arguments)), b || a.exports && Z(a.exports)
                }
            },
            makeRequire: function (a, d) {
                function g(e, c, u) {
                    var i, m;
                    return d.enableBuildCallback && c && I(c) && (c.__requireJsBuild = !0), "string" == typeof e ? I(c) ? A(F("requireargs", "Invalid require call"), u) : a && r(N, e) ? N[e](j[a.id]) : l.get ? l.get(k, e, a) : (i = h(e, a, !1, !0), i = i.id, r(p, i) ? p[i] : A(F("notloaded", 'Module name "' + i + '" has not been loaded yet for context: ' + b + (a ? "" : ". Use require([])")))) : (K(), k.nextTick(function () {
                        K(), m = q(h(null, a)), m.skipMap = d.skipMap, m.init(e, c, u, {
                            enabled: !0
                        }), C()
                    }), g)
                }
                return d = d || {}, Q(g, {
                    isBrowser: z,
                    toUrl: function (b) {
                        var d, f = b.lastIndexOf("."),
                            h = b.split("/")[0];
                        return -1 !== f && ("." !== h && ".." !== h || f > 1) && (d = b.substring(f, b.length), b = b.substring(0, f)), b = k.nameToUrl(c(b, a && a.id, !0), d || ".fake"), d ? b : b.substring(0, b.length - 5)
                    },
                    defined: function (b) {
                        return r(p, h(b, a, !1, !0).id)
                    },
                    specified: function (b) {
                        return b = h(b, a, !1, !0).id, r(p, b) || r(j, b)
                    }
                }), a || (g.undef = function (b) {
                    w();
                    var c = h(b, a, !0),
                        d = i(j, b);
                    delete p[b], delete S[c.url], delete X[b], d && (d.events.defined && (X[b] = d.events), delete j[b])
                }), g
            },
            enable: function (a) {
                i(j, a.id) && q(a).enable()
            },
            completeLoad: function (a) {
                var b, c, d = i(m.shim, a) || {},
                    h = d.exports;
                for (w(); G.length;) {
                    if (c = G.shift(), null === c[0]) {
                        if (c[0] = a, b) break;
                        b = !0
                    } else c[0] === a && (b = !0);
                    D(c)
                }
                if (c = i(j, a), !b && !r(p, a) && c && !c.inited) {
                    if (m.enforceDefine && (!h || !Z(h))) return y(a) ? void 0 : A(F("nodefine", "No define call for " + a, null, [a]));
                    D([a, d.deps || [], d.exportsFn])
                }
                C()
            },
            nameToUrl: function (a, b) {
                var c, d, h, g, k, j;
                if (l.jsExtRegExp.test(a)) g = a + (b || "");
                else {
                    for (c = m.paths, d = m.pkgs, g = a.split("/"), k = g.length; k > 0; k -= 1) {
                        if (j = g.slice(0, k).join("/"), h = i(d, j), j = i(c, j)) {
                            J(j) && (j = j[0]), g.splice(0, k, j);
                            break
                        }
                        if (h) {
                            c = a === h.name ? h.location + "/" + h.main : h.location, g.splice(0, k, c);
                            break
                        }
                    }
                    g = g.join("/"), g += b || (/\?/.test(g) ? "" : ".js"), g = ("/" === g.charAt(0) || g.match(/^[\w\+\.\-]+:/) ? "" : m.baseUrl) + g
                }
                return m.urlArgs ? g + ((-1 === g.indexOf("?") ? "?" : "&") + m.urlArgs) : g
            },
            load: function (a, b) {
                l.load(k, a, b)
            },
            execCb: function (a, b, c, d) {
                return b.apply(d, c)
            },
            onScriptLoad: function (a) {
                ("load" === a.type || ha.test((a.currentTarget || a.srcElement).readyState)) && (P = null, a = H(a), k.completeLoad(a.id))
            },
            onScriptError: function (a) {
                var b = H(a);
                return y(b.id) ? void 0 : A(F("scripterror", "Script error", a, [b.id]))
            }
        }, k.require = k.makeRequire(), k
    }
    var l, w, B, D, s, H, P, K, ba, ca, ia = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/gm,
        ja = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
        aa = /\.js$/,
        ga = /^\.\//;
    w = Object.prototype;
    var L = w.toString,
        da = w.hasOwnProperty,
        fa = Array.prototype.splice,
        z = !("undefined" == typeof window || !navigator || !document),
        $ = !z && "undefined" != typeof importScripts,
        ha = z && "PLAYSTATION 3" === navigator.platform ? /^complete$/ : /^(complete|loaded)$/,
        V = "undefined" != typeof opera && "[object Opera]" === opera.toString(),
        C = {},
        q = {},
        R = [],
        O = !1;
    if ("undefined" == typeof define) {
        if ("undefined" != typeof requirejs) {
            if (I(requirejs)) return;
            q = requirejs, requirejs = void 0
        }
        "undefined" != typeof require && !I(require) && (q = require, require = void 0), l = requirejs = function (b, c, d, y) {
            var g, h = "_";
            return !J(b) && "string" != typeof b && (g = b, J(c) ? (b = c, c = d, d = y) : b = []), g && g.context && (h = g.context), (y = i(C, h)) || (y = C[h] = l.s.newContext(h)), g && y.configure(g), y.require(b, c, d)
        }, l.config = function (b) {
            return l(b)
        }, l.nextTick = "undefined" != typeof setTimeout ? function (b) {
            setTimeout(b, 4)
        } : function (b) {
            b()
        }, require || (require = l), l.version = "2.1.4", l.jsExtRegExp = /^\/|:|\?|\.js$/, l.isBrowser = z, w = l.s = {
            contexts: C,
            newContext: ea
        }, l({}), x(["toUrl", "undef", "defined", "specified"], function (b) {
            l[b] = function () {
                var c = C._;
                return c.require[b].apply(c, arguments)
            }
        }), z && (B = w.head = document.getElementsByTagName("head")[0], D = document.getElementsByTagName("base")[0]) && (B = w.head = D.parentNode), l.onError = function (b) {
            throw b
        }, l.load = function (b, c, d) {
            var g, i = b && b.config || {};
            return z ? (g = i.xhtml ? document.createElementNS("http://www.w3.org/1999/xhtml", "html:script") : document.createElement("script"), g.type = i.scriptType || "text/javascript", g.charset = "utf-8", g.async = !0, g.setAttribute("data-requirecontext", b.contextName), g.setAttribute("data-requiremodule", c), !g.attachEvent || g.attachEvent.toString && 0 > g.attachEvent.toString().indexOf("[native code") || V ? (g.addEventListener("load", b.onScriptLoad, !1), g.addEventListener("error", b.onScriptError, !1)) : (O = !0, g.attachEvent("onreadystatechange", b.onScriptLoad)), g.src = d, K = g, D ? B.insertBefore(g, D) : B.appendChild(g), K = null, g) : ($ && (importScripts(d), b.completeLoad(c)), void 0)
        }, z && M(document.getElementsByTagName("script"), function (b) {
            return B || (B = b.parentNode), (s = b.getAttribute("data-main")) ? (q.baseUrl || (H = s.split("/"), ba = H.pop(), ca = H.length ? H.join("/") + "/" : "./", q.baseUrl = ca, s = ba), s = s.replace(aa, ""), q.deps = q.deps ? q.deps.concat(s) : [s], !0) : void 0
        }), define = function (b, c, d) {
            var i, g;
            "string" != typeof b && (d = c, c = b, b = null), J(c) || (d = c, c = []), !c.length && I(d) && d.length && (d.toString().replace(ia, "").replace(ja, function (b, d) {
                c.push(d)
            }), c = (1 === d.length ? ["require"] : ["require", "exports", "module"]).concat(c)), O && ((i = K) || (P && "interactive" === P.readyState || M(document.getElementsByTagName("script"), function (b) {
                return "interactive" === b.readyState ? P = b : void 0
            }), i = P), i && (b || (b = i.getAttribute("data-requiremodule")), g = C[i.getAttribute("data-requirecontext")])), (g ? g.defQueue : R).push([b, c, d])
        }, define.amd = {
            jQuery: !0
        }, l.exec = function (b) {
            return eval(b)
        }, l(q)
    }
}(this),
function (k) {
    var o = String.prototype.trim,
        l = function (a, b) {
            for (var f = []; b > 0; f[--b] = a);
            return f.join("")
        },
        c = function (a) {
            return function () {
                for (var b = Array.prototype.slice.call(arguments), f = 0; f < b.length; f++) b[f] = null == b[f] ? "" : "" + b[f];
                return a.apply(null, b)
            }
        },
        m = function () {
            function a(a) {
                return Object.prototype.toString.call(a).slice(8, -1).toLowerCase()
            }
            var b = function () {
                return b.cache.hasOwnProperty(arguments[0]) || (b.cache[arguments[0]] = b.parse(arguments[0])), b.format.call(null, b.cache[arguments[0]], arguments)
            };
            return b.format = function (b, n) {
                var i, j, g, k, h = 1,
                    d = b.length,
                    e = "",
                    c = [];
                for (i = 0; d > i; i++)
                    if (e = a(b[i]), "string" === e) c.push(b[i]);
                    else if ("array" === e) {
                    if (g = b[i], g[2])
                        for (e = n[h], j = 0; j < g[2].length; j++) {
                            if (!e.hasOwnProperty(g[2][j])) throw m('[_.sprintf] property "%s" does not exist', g[2][j]);
                            e = e[g[2][j]]
                        } else e = g[1] ? n[g[1]] : n[h++];
                    if (/[^s]/.test(g[8]) && "number" != a(e)) throw m("[_.sprintf] expecting number but found %s", a(e));
                    switch (g[8]) {
                    case "b":
                        e = e.toString(2);
                        break;
                    case "c":
                        e = String.fromCharCode(e);
                        break;
                    case "d":
                        e = parseInt(e, 10);
                        break;
                    case "e":
                        e = g[7] ? e.toExponential(g[7]) : e.toExponential();
                        break;
                    case "f":
                        e = g[7] ? parseFloat(e).toFixed(g[7]) : parseFloat(e);
                        break;
                    case "o":
                        e = e.toString(8);
                        break;
                    case "s":
                        e = (e = "" + e) && g[7] ? e.substring(0, g[7]) : e;
                        break;
                    case "u":
                        e = Math.abs(e);
                        break;
                    case "x":
                        e = e.toString(16);
                        break;
                    case "X":
                        e = e.toString(16).toUpperCase()
                    }
                    e = /[def]/.test(g[8]) && g[3] && e >= 0 ? "+" + e : e, j = g[4] ? "0" == g[4] ? "0" : g[4].charAt(1) : " ", k = g[6] - ("" + e).length, j = g[6] ? l(j, k) : "", c.push(g[5] ? e + j : j + e)
                }
                return c.join("")
            }, b.cache = {}, b.parse = function (a) {
                for (var b = [], h = [], c = 0; a;) {
                    if (null !== (b = /^[^\x25]+/.exec(a))) h.push(b[0]);
                    else if (null !== (b = /^\x25{2}/.exec(a))) h.push("%");
                    else {
                        if (null === (b = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(a))) throw "[_.sprintf] huh?";
                        if (b[2]) {
                            var c = 1 | c,
                                e = [],
                                d = b[2],
                                i = [];
                            if (null === (i = /^([a-z_][a-z_\d]*)/i.exec(d))) throw "[_.sprintf] huh?";
                            for (e.push(i[1]);
                                "" !== (d = d.substring(i[0].length));)
                                if (null !== (i = /^\.([a-z_][a-z_\d]*)/i.exec(d))) e.push(i[1]);
                                else {
                                    if (null === (i = /^\[(\d+)\]/.exec(d))) throw "[_.sprintf] huh?";
                                    e.push(i[1])
                                }
                            b[2] = e
                        } else c |= 2; if (3 === c) throw "[_.sprintf] mixing positional and named placeholders is not (yet) supported";
                        h.push(b)
                    }
                    a = a.substring(b[0].length)
                }
                return h
            }, b
        }(),
        d = {
            VERSION: "2.0.0",
            isBlank: c(function (a) {
                return /^\s*$/.test(a)
            }),
            stripTags: c(function (a) {
                return a.replace(/<\/?[^>]+>/gi, "")
            }),
            capitalize: c(function (a) {
                return a.charAt(0).toUpperCase() + a.substring(1).toLowerCase()
            }),
            chop: c(function (a, b) {
                for (var b = 1 * b || 0 || a.length, f = [], c = 0; c < a.length;) f.push(a.slice(c, c + b)), c += b;
                return f
            }),
            clean: c(function (a) {
                return d.strip(a.replace(/\s+/g, " "))
            }),
            count: c(function (a, b) {
                for (var c, f = 0, d = 0; d < a.length;) c = a.indexOf(b, d), c >= 0 && f++, d = d + (c >= 0 ? c : 0) + b.length;
                return f
            }),
            chars: c(function (a) {
                return a.split("")
            }),
            escapeHTML: c(function (a) {
                return a.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;")
            }),
            unescapeHTML: c(function (a) {
                return a.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&amp;/g, "&")
            }),
            escapeRegExp: c(function (a) {
                return a.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1")
            }),
            insert: c(function (a, b, f) {
                return a = a.split(""), a.splice(1 * b || 0, 0, f), a.join("")
            }),
            include: c(function (a, b) {
                return -1 !== a.indexOf(b)
            }),
            join: c(function () {
                var b = Array.prototype.slice.call(arguments);
                return b.join(b.shift())
            }),
            lines: c(function (a) {
                return a.split("\n")
            }),
            reverse: c(function (a) {
                return Array.prototype.reverse.apply(("" + a).split("")).join("")
            }),
            splice: c(function (a, b, f, c) {
                return a = a.split(""), a.splice(1 * b || 0, 1 * f || 0, c), a.join("")
            }),
            startsWith: c(function (a, b) {
                return a.length >= b.length && a.substring(0, b.length) === b
            }),
            endsWith: c(function (a, b) {
                return a.length >= b.length && a.substring(a.length - b.length) === b
            }),
            succ: c(function (a) {
                var b = a.split("");
                return b.splice(a.length - 1, 1, String.fromCharCode(a.charCodeAt(a.length - 1) + 1)), b.join("")
            }),
            titleize: c(function (a) {
                for (var b, a = a.split(" "), f = 0; f < a.length; f++) b = a[f].split(""), "undefined" != typeof b[0] && (b[0] = b[0].toUpperCase()), a[f] = f + 1 === a.length ? b.join("") : b.join("") + " ";
                return a.join("")
            }),
            camelize: c(function (a) {
                return d.trim(a).replace(/(\-|_|\s)+(.)?/g, function (a, f, c) {
                    return c ? c.toUpperCase() : ""
                })
            }),
            underscored: function (a) {
                return d.trim(a).replace(/([a-z\d])([A-Z]+)/g, "$1_$2").replace(/\-|\s+/g, "_").toLowerCase()
            },
            dasherize: function (a) {
                return d.trim(a).replace(/([a-z\d])([A-Z]+)/g, "$1-$2").replace(/^([A-Z]+)/, "-$1").replace(/\_|\s+/g, "-").toLowerCase()
            },
            humanize: function (a) {
                return d.capitalize(this.underscored(a).replace(/_id$/, "").replace(/_/g, " "))
            },
            trim: c(function (a, b) {
                return !b && o ? o.call(a) : (b = b ? d.escapeRegExp(b) : "\\s", a.replace(RegExp("^[" + b + "]+|[" + b + "]+$", "g"), ""))
            }),
            ltrim: c(function (a, b) {
                return b = b ? d.escapeRegExp(b) : "\\s", a.replace(RegExp("^[" + b + "]+", "g"), "")
            }),
            rtrim: c(function (a, b) {
                return b = b ? d.escapeRegExp(b) : "\\s", a.replace(RegExp("[" + b + "]+$", "g"), "")
            }),
            truncate: c(function (a, b, f) {
                return b = 1 * b || 0, a.length > b ? a.slice(0, b) + (f || "...") : a
            }),
            prune: c(function (a, b, f) {
                var c = "",
                    h = "",
                    h = 0,
                    f = f || "...",
                    b = 1 * b || 0;
                for (h in a) c += a[h].toUpperCase() != a[h].toLowerCase() || /[-_\d]/.test(a[h]) ? "A" : " ";
                return h = 0 === c.substring(b - 1, b + 1).search(/^\w\w$/) ? d.rtrim(c.slice(0, b).replace(/([\W][\w]*)$/, "")) : d.rtrim(c.slice(0, b)), h = h.replace(/\W+$/, ""), h.length + f.length > a.length ? a : a.substring(0, h.length) + f
            }),
            words: function (a, b) {
                return ("" + a).split(b || " ")
            },
            pad: c(function (a, b, f, c) {
                var d = "",
                    d = 0,
                    b = 1 * b || 0;
                switch (f ? 1 < f.length && (f = f.charAt(0)) : f = " ", c) {
                case "right":
                    d = b - a.length, d = l(f, d), a += d;
                    break;
                case "both":
                    d = b - a.length, d = {
                        left: l(f, Math.ceil(d / 2)),
                        right: l(f, Math.floor(d / 2))
                    }, a = d.left + a + d.right;
                    break;
                default:
                    d = b - a.length, d = l(f, d), a = d + a
                }
                return a
            }),
            lpad: function (a, b, c) {
                return d.pad(a, b, c)
            },
            rpad: function (a, b, c) {
                return d.pad(a, b, c, "right")
            },
            lrpad: function (a, b, c) {
                return d.pad(a, b, c, "both")
            },
            sprintf: m,
            vsprintf: function (a, b) {
                return b.unshift(a), m.apply(null, b)
            },
            toNumber: function (a, b) {
                var c;
                return c = 1 * (1 * a || 0).toFixed(1 * b || 0) || 0, 0 !== c || "0" === a || 0 === a ? c : Number.NaN
            },
            strRight: c(function (a, b) {
                var c = b ? a.indexOf(b) : -1;
                return -1 != c ? a.slice(c + b.length, a.length) : a
            }),
            strRightBack: c(function (a, b) {
                var c = b ? a.lastIndexOf(b) : -1;
                return -1 != c ? a.slice(c + b.length, a.length) : a
            }),
            strLeft: c(function (a, b) {
                var c = b ? a.indexOf(b) : -1;
                return -1 != c ? a.slice(0, c) : a
            }),
            strLeftBack: c(function (a, b) {
                var c = a.lastIndexOf(b);
                return -1 != c ? a.slice(0, c) : a
            }),
            exports: function () {
                var b, a = {};
                for (b in this) this.hasOwnProperty(b) && "include" != b && "contains" != b && "reverse" != b && (a[b] = this[b]);
                return a
            }
        };
    d.strip = d.trim, d.lstrip = d.ltrim, d.rstrip = d.rtrim, d.center = d.lrpad, d.ljust = d.lpad, d.rjust = d.rpad, d.contains = d.include, "undefined" != typeof exports ? ("undefined" != typeof module && module.exports && (module.exports = d), exports._s = d) : "undefined" != typeof k._ ? (k._.string = d, k._.str = k._.string) : k._ = {
        string: d,
        str: d
    }
}(this || window),
function () {
    var e;
    e = function () {
        function e() {
            this.options_index = 0, this.parsed = []
        }
        return e.prototype.add_node = function (e) {
            return "OPTGROUP" === e.nodeName.toUpperCase() ? this.add_group(e) : this.add_option(e)
        }, e.prototype.add_group = function (e) {
            var t, n, r, i, s, o;
            for (t = this.parsed.length, this.parsed.push({
                array_index: t,
                group: !0,
                label: e.label,
                children: 0,
                disabled: e.disabled
            }), s = e.childNodes, o = [], r = 0, i = s.length; i > r; r++) n = s[r], o.push(this.add_option(n, t, e.disabled));
            return o
        }, e.prototype.add_option = function (e, t, n) {
            return "OPTION" === e.nodeName.toUpperCase() ? ("" !== e.text ? (null != t && (this.parsed[t].children += 1), this.parsed.push({
                array_index: this.parsed.length,
                options_index: this.options_index,
                value: e.value,
                text: e.text,
                html: e.innerHTML,
                selected: e.selected,
                disabled: n === !0 ? n : e.disabled,
                group_array_index: t,
                classes: e.className,
                style: e.style.cssText
            })) : this.parsed.push({
                array_index: this.parsed.length,
                options_index: this.options_index,
                empty: !0
            }), this.options_index += 1) : void 0
        }, e
    }(), e.select_to_array = function (t) {
        var n, r, i, s, o;
        for (r = new e, o = t.childNodes, i = 0, s = o.length; s > i; i++) n = o[i], r.add_node(n);
        return r.parsed
    }, this.SelectParser = e
}.call(this),
function () {
    var e, t;
    t = this, e = function () {
        function e(e, t) {
            this.form_field = e, this.options = null != t ? t : {}, this.is_multiple = this.form_field.multiple, this.set_default_text(), this.set_default_values(), this.setup(), this.set_up_html(), this.register_observers(), this.finish_setup()
        }
        return e.prototype.set_default_values = function () {
            var e = this;
            return this.click_test_action = function (t) {
                return e.test_active_click(t)
            }, this.activate_action = function (t) {
                return e.activate_field(t)
            }, this.active_field = !1, this.mouse_on_container = !1, this.results_showing = !1, this.result_highlighted = null, this.result_single_selected = null, this.allow_single_deselect = null != this.options.allow_single_deselect && null != this.form_field.options[0] && "" === this.form_field.options[0].text ? this.options.allow_single_deselect : !1, this.disable_search_threshold = this.options.disable_search_threshold || 0, this.disable_search = this.options.disable_search || !1, this.enable_split_word_search = null != this.options.enable_split_word_search ? this.options.enable_split_word_search : !0, this.search_contains = this.options.search_contains || !1, this.choices = 0, this.single_backstroke_delete = this.options.single_backstroke_delete || !1, this.max_selected_options = this.options.max_selected_options || 1 / 0, this.inherit_select_classes = this.options.inherit_select_classes || !1
        }, e.prototype.set_default_text = function () {
            return this.default_text = this.form_field.getAttribute("data-placeholder") ? this.form_field.getAttribute("data-placeholder") : this.is_multiple ? this.options.placeholder_text_multiple || this.options.placeholder_text || "Select Some Options" : this.options.placeholder_text_single || this.options.placeholder_text || "Select an Option", this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || "No results match"
        }, e.prototype.mouse_enter = function () {
            return this.mouse_on_container = !0
        }, e.prototype.mouse_leave = function () {
            return this.mouse_on_container = !1
        }, e.prototype.input_focus = function () {
            var t = this;
            if (this.is_multiple) {
                if (!this.active_field) return setTimeout(function () {
                    return t.container_mousedown()
                }, 50)
            } else if (!this.active_field) return this.activate_field()
        }, e.prototype.input_blur = function () {
            var t = this;
            return this.mouse_on_container ? void 0 : (this.active_field = !1, setTimeout(function () {
                return t.blur_test()
            }, 100))
        }, e.prototype.result_add_option = function (e) {
            var t, n;
            return e.disabled ? "" : (e.dom_id = this.container_id + "_o_" + e.array_index, t = e.selected && this.is_multiple ? [] : ["active-result"], e.selected && t.push("result-selected"), null != e.group_array_index && t.push("group-option"), "" !== e.classes && t.push(e.classes), n = "" !== e.style.cssText ? ' style="' + e.style + '"' : "", '<li id="' + e.dom_id + '" class="' + t.join(" ") + '"' + n + ">" + e.html + "</li>")
        }, e.prototype.results_update_field = function () {
            return this.is_multiple || this.results_reset_cleanup(), this.result_clear_highlight(), this.result_single_selected = null, this.results_build()
        }, e.prototype.results_toggle = function () {
            return this.results_showing ? this.results_hide() : this.results_show()
        }, e.prototype.results_search = function () {
            return this.results_showing ? this.winnow_results() : this.results_show()
        }, e.prototype.keyup_checker = function (e) {
            var t, n;
            switch (t = null != (n = e.which) ? n : e.keyCode, this.search_field_scale(), t) {
            case 8:
                if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0) return this.keydown_backstroke();
                if (!this.pending_backstroke) return this.result_clear_highlight(), this.results_search();
                break;
            case 13:
                if (e.preventDefault(), this.results_showing) return this.result_select(e);
                break;
            case 27:
                return this.results_showing && this.results_hide(), !0;
            case 9:
            case 38:
            case 40:
            case 16:
            case 91:
            case 17:
                break;
            default:
                return this.results_search()
            }
        }, e.prototype.generate_field_id = function () {
            var e;
            return e = this.generate_random_id(), this.form_field.id = e, e
        }, e.prototype.generate_random_char = function () {
            var e, t, n;
            return e = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", n = Math.floor(Math.random() * e.length), t = e.substring(n, n + 1)
        }, e
    }(), t.AbstractChosen = e
}.call(this),
function () {
    var e, t, n, r, i = {}.hasOwnProperty,
        s = function (e, t) {
            function r() {
                this.constructor = e
            }
            for (var n in t) i.call(t, n) && (e[n] = t[n]);
            return r.prototype = t.prototype, e.prototype = new r, e.__super__ = t.prototype, e
        };
    r = this, e = jQuery, e.fn.extend({
        chosen: function (n) {
            var r, i, s;
            return s = navigator.userAgent.toLowerCase(), i = /(msie) ([\w.]+)/.exec(s) || [], r = {
                name: i[1] || "",
                version: i[2] || "0"
            }, "msie" === r.name && ("6.0" === r.version || "7.0" === r.version && 7 === document.documentMode) ? this : this.each(function () {
                var i;
                return i = e(this), i.hasClass("chzn-done") ? void 0 : i.data("chosen", new t(this, n))
            })
        }
    }), t = function (t) {
        function i() {
            return i.__super__.constructor.apply(this, arguments)
        }
        return s(i, t), i.prototype.setup = function () {
            return this.form_field_jq = e(this.form_field), this.current_value = this.form_field_jq.val(), this.is_rtl = this.form_field_jq.hasClass("chzn-rtl")
        }, i.prototype.finish_setup = function () {
            return this.form_field_jq.addClass("chzn-done")
        }, i.prototype.set_up_html = function () {
            var t, r, i, s, o, u;
            return this.container_id = this.form_field.id.length ? this.form_field.id.replace(/[^\w]/g, "_") : this.generate_field_id(), this.container_id += "_chzn", t = ["chzn-container"], t.push("chzn-container-" + (this.is_multiple ? "multi" : "single")), this.inherit_select_classes && this.form_field.className && t.push(this.form_field.className), this.is_rtl && t.push("chzn-rtl"), this.f_width = this.form_field_jq.outerWidth(), i = {
                id: this.container_id,
                "class": t.join(" "),
                style: "width: " + this.f_width + "px;",
                title: this.form_field.title
            }, r = e("<div />", i), this.is_multiple ? r.html('<ul class="chzn-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chzn-drop" style="left:-9000px;"><ul class="chzn-results"></ul></div>') : r.html('<a href="javascript:void(0)" class="chzn-single chzn-default" tabindex="-1"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chzn-drop" style="left:-9000px;"><div class="chzn-search"><input type="text" autocomplete="off" /></div><ul class="chzn-results"></ul></div>'), this.form_field_jq.hide().after(r), this.container = e("#" + this.container_id), this.dropdown = this.container.find("div.chzn-drop").first(), s = this.container.height(), o = this.f_width - n(this.dropdown), this.dropdown.css({
                width: o + "px",
                top: s + "px"
            }), this.search_field = this.container.find("input").first(), this.search_results = this.container.find("ul.chzn-results").first(), this.search_field_scale(), this.search_no_results = this.container.find("li.no-results").first(), this.is_multiple ? (this.search_choices = this.container.find("ul.chzn-choices").first(), this.search_container = this.container.find("li.search-field").first()) : (this.search_container = this.container.find("div.chzn-search").first(), this.selected_item = this.container.find(".chzn-single").first(), u = o - n(this.search_container) - n(this.search_field), this.search_field.css({
                width: u + "px"
            })), this.results_build(), this.set_tab_index(), this.form_field_jq.trigger("liszt:ready", {
                chosen: this
            })
        }, i.prototype.register_observers = function () {
            var e = this;
            return this.container.mousedown(function (t) {
                return e.container_mousedown(t)
            }), this.container.mouseup(function (t) {
                return e.container_mouseup(t)
            }), this.container.mouseenter(function (t) {
                return e.mouse_enter(t)
            }), this.container.mouseleave(function (t) {
                return e.mouse_leave(t)
            }), this.search_results.mouseup(function (t) {
                return e.search_results_mouseup(t)
            }), this.search_results.mouseover(function (t) {
                return e.search_results_mouseover(t)
            }), this.search_results.mouseout(function (t) {
                return e.search_results_mouseout(t)
            }), this.form_field_jq.bind("liszt:updated", function (t) {
                return e.results_update_field(t)
            }), this.form_field_jq.bind("liszt:activate", function (t) {
                return e.activate_field(t)
            }), this.form_field_jq.bind("liszt:open", function (t) {
                return e.container_mousedown(t)
            }), this.search_field.blur(function (t) {
                return e.input_blur(t)
            }), this.search_field.keyup(function (t) {
                return e.keyup_checker(t)
            }), this.search_field.keydown(function (t) {
                return e.keydown_checker(t)
            }), this.search_field.focus(function (t) {
                return e.input_focus(t)
            }), this.is_multiple ? this.search_choices.click(function (t) {
                return e.choices_click(t)
            }) : this.container.click(function (e) {
                return e.preventDefault()
            })
        }, i.prototype.search_field_disabled = function () {
            return this.is_disabled = this.form_field_jq[0].disabled, this.is_disabled ? (this.container.addClass("chzn-disabled"), this.search_field[0].disabled = !0, this.is_multiple || this.selected_item.unbind("focus", this.activate_action), this.close_field()) : (this.container.removeClass("chzn-disabled"), this.search_field[0].disabled = !1, this.is_multiple ? void 0 : this.selected_item.bind("focus", this.activate_action))
        }, i.prototype.container_mousedown = function (t) {
            var n;
            return this.is_disabled ? void 0 : (n = null != t ? e(t.target).hasClass("search-choice-close") : !1, t && "mousedown" === t.type && !this.results_showing && t.preventDefault(), this.pending_destroy_click || n ? this.pending_destroy_click = !1 : (this.active_field ? !this.is_multiple && t && (e(t.target)[0] === this.selected_item[0] || e(t.target).parents("a.chzn-single").length) && (t.preventDefault(), this.results_toggle()) : (this.is_multiple && this.search_field.val(""), e(document).click(this.click_test_action), this.results_show()), this.activate_field()))
        }, i.prototype.container_mouseup = function (e) {
            return "ABBR" !== e.target.nodeName || this.is_disabled ? void 0 : this.results_reset(e)
        }, i.prototype.blur_test = function () {
            return !this.active_field && this.container.hasClass("chzn-container-active") ? this.close_field() : void 0
        }, i.prototype.close_field = function () {
            return e(document).unbind("click", this.click_test_action), this.active_field = !1, this.results_hide(), this.container.removeClass("chzn-container-active"), this.winnow_results_clear(), this.clear_backstroke(), this.show_search_field_default(), this.search_field_scale()
        }, i.prototype.activate_field = function () {
            return this.container.addClass("chzn-container-active"), this.active_field = !0, this.search_field.val(this.search_field.val()), this.search_field.focus()
        }, i.prototype.test_active_click = function (t) {
            return e(t.target).parents("#" + this.container_id).length ? this.active_field = !0 : this.close_field()
        }, i.prototype.results_build = function () {
            var e, t, n, i, s;
            for (this.parsing = !0, this.results_data = r.SelectParser.select_to_array(this.form_field), this.is_multiple && this.choices > 0 ? (this.search_choices.find("li.search-choice").remove(), this.choices = 0) : this.is_multiple || (this.selected_item.addClass("chzn-default").find("span").text(this.default_text), this.disable_search || this.form_field.options.length <= this.disable_search_threshold ? this.container.addClass("chzn-container-single-nosearch") : this.container.removeClass("chzn-container-single-nosearch")), e = "", s = this.results_data, n = 0, i = s.length; i > n; n++) t = s[n], t.group ? e += this.result_add_group(t) : t.empty || (e += this.result_add_option(t), t.selected && this.is_multiple ? this.choice_build(t) : t.selected && !this.is_multiple && (this.selected_item.removeClass("chzn-default").find("span").text(t.text), this.allow_single_deselect && this.single_deselect_control_build()));
            return this.search_field_disabled(), this.show_search_field_default(), this.search_field_scale(), this.search_results.html(e), this.parsing = !1
        }, i.prototype.result_add_group = function (t) {
            return t.disabled ? "" : (t.dom_id = this.container_id + "_g_" + t.array_index, '<li id="' + t.dom_id + '" class="group-result">' + e("<div />").text(t.label).html() + "</li>")
        }, i.prototype.result_do_highlight = function (e) {
            var t, n, r, i, s;
            if (e.length) {
                if (this.result_clear_highlight(), this.result_highlight = e, this.result_highlight.addClass("highlighted"), r = parseInt(this.search_results.css("maxHeight"), 10), s = this.search_results.scrollTop(), i = r + s, n = this.result_highlight.position().top + this.search_results.scrollTop(), t = n + this.result_highlight.outerHeight(), t >= i) return this.search_results.scrollTop(t - r > 0 ? t - r : 0);
                if (s > n) return this.search_results.scrollTop(n)
            }
        }, i.prototype.result_clear_highlight = function () {
            return this.result_highlight && this.result_highlight.removeClass("highlighted"), this.result_highlight = null
        }, i.prototype.results_show = function () {
            var e;
            if (this.is_multiple) {
                if (this.max_selected_options <= this.choices) return this.form_field_jq.trigger("liszt:maxselected", {
                    chosen: this
                }), !1
            } else this.selected_item.addClass("chzn-single-with-drop"), this.result_single_selected && this.result_do_highlight(this.result_single_selected);
            return e = this.is_multiple ? this.container.height() : this.container.height() - 1, this.form_field_jq.trigger("liszt:showing_dropdown", {
                chosen: this
            }), this.dropdown.css({
                top: e + "px",
                left: 0
            }), this.results_showing = !0, this.search_field.focus(), this.search_field.val(this.search_field.val()), this.winnow_results()
        }, i.prototype.results_hide = function () {
            return this.is_multiple || this.selected_item.removeClass("chzn-single-with-drop"), this.result_clear_highlight(), this.form_field_jq.trigger("liszt:hiding_dropdown", {
                chosen: this
            }), this.dropdown.css({
                left: "-9000px"
            }), this.results_showing = !1
        }, i.prototype.set_tab_index = function () {
            var t;
            return this.form_field_jq.attr("tabindex") ? (t = this.form_field_jq.attr("tabindex"), this.form_field_jq.attr("tabindex", -1), this.search_field.attr("tabindex", t)) : void 0
        }, i.prototype.show_search_field_default = function () {
            return this.is_multiple && this.choices < 1 && !this.active_field ? (this.search_field.val(this.default_text), this.search_field.addClass("default")) : (this.search_field.val(""), this.search_field.removeClass("default"))
        }, i.prototype.search_results_mouseup = function (t) {
            var n;
            return n = e(t.target).hasClass("active-result") ? e(t.target) : e(t.target).parents(".active-result").first(), n.length ? (this.result_highlight = n, this.result_select(t), this.search_field.focus()) : void 0
        }, i.prototype.search_results_mouseover = function (t) {
            var n;
            return n = e(t.target).hasClass("active-result") ? e(t.target) : e(t.target).parents(".active-result").first(), n ? this.result_do_highlight(n) : void 0
        }, i.prototype.search_results_mouseout = function (t) {
            return e(t.target).hasClass("active-result") ? this.result_clear_highlight() : void 0
        }, i.prototype.choices_click = function (t) {
            return t.preventDefault(), !this.active_field || e(t.target).hasClass("search-choice") || this.results_showing ? void 0 : this.results_show()
        }, i.prototype.choice_build = function (t) {
            var n, r, i, s = this;
            return this.is_multiple && this.max_selected_options <= this.choices ? (this.form_field_jq.trigger("liszt:maxselected", {
                chosen: this
            }), !1) : (n = this.container_id + "_c_" + t.array_index, this.choices += 1, r = t.disabled ? '<li class="search-choice search-choice-disabled" id="' + n + '"><span>' + t.html + "</span></li>" : '<li class="search-choice" id="' + n + '"><span>' + t.html + '</span><a href="javascript:void(0)" class="search-choice-close" rel="' + t.array_index + '"></a></li>', this.search_container.before(r), i = e("#" + n).find("a").first(), i.click(function (e) {
                return s.choice_destroy_link_click(e)
            }))
        }, i.prototype.choice_destroy_link_click = function (t) {
            return t.preventDefault(), this.is_disabled ? t.stopPropagation : (this.pending_destroy_click = !0, this.choice_destroy(e(t.target)))
        }, i.prototype.choice_destroy = function (e) {
            return this.result_deselect(e.attr("rel")) ? (this.choices -= 1, this.show_search_field_default(), this.is_multiple && this.choices > 0 && this.search_field.val().length < 1 && this.results_hide(), e.parents("li").first().remove(), this.search_field_scale()) : void 0
        }, i.prototype.results_reset = function () {
            return this.form_field.options[0].selected = !0, this.selected_item.find("span").text(this.default_text), this.is_multiple || this.selected_item.addClass("chzn-default"), this.show_search_field_default(), this.results_reset_cleanup(), this.form_field_jq.trigger("change"), this.active_field ? this.results_hide() : void 0
        }, i.prototype.results_reset_cleanup = function () {
            return this.current_value = this.form_field_jq.val(), this.selected_item.find("abbr").remove()
        }, i.prototype.result_select = function (e) {
            var t, n, r, i;
            return this.result_highlight ? (t = this.result_highlight, n = t.attr("id"), this.result_clear_highlight(), this.is_multiple ? this.result_deactivate(t) : (this.search_results.find(".result-selected").removeClass("result-selected"), this.result_single_selected = t, this.selected_item.removeClass("chzn-default")), t.addClass("result-selected"), i = n.substr(n.lastIndexOf("_") + 1), r = this.results_data[i], r.selected = !0, this.form_field.options[r.options_index].selected = !0, this.is_multiple ? this.choice_build(r) : (this.selected_item.find("span").first().text(r.text), this.allow_single_deselect && this.single_deselect_control_build()), (!e.metaKey && !e.ctrlKey || !this.is_multiple) && this.results_hide(), this.search_field.val(""), (this.is_multiple || this.form_field_jq.val() !== this.current_value) && this.form_field_jq.trigger("change", {
                selected: this.form_field.options[r.options_index].value
            }), this.current_value = this.form_field_jq.val(), this.search_field_scale()) : void 0
        }, i.prototype.result_activate = function (e) {
            return e.addClass("active-result")
        }, i.prototype.result_deactivate = function (e) {
            return e.removeClass("active-result")
        }, i.prototype.result_deselect = function (t) {
            var n, r;
            return r = this.results_data[t], this.form_field.options[r.options_index].disabled ? !1 : (r.selected = !1, this.form_field.options[r.options_index].selected = !1, n = e("#" + this.container_id + "_o_" + t), n.removeClass("result-selected").addClass("active-result").show(), this.result_clear_highlight(), this.winnow_results(), this.form_field_jq.trigger("change", {
                deselected: this.form_field.options[r.options_index].value
            }), this.search_field_scale(), !0)
        }, i.prototype.single_deselect_control_build = function () {
            return this.allow_single_deselect && this.selected_item.find("abbr").length < 1 ? this.selected_item.find("span").first().after('<abbr class="search-choice-close"></abbr>') : void 0
        }, i.prototype.winnow_results = function () {
            var t, n, r, i, s, o, u, a, f, l, c, h, p, d, v, m, g, y;
            for (this.no_results_clear(), f = 0, l = this.search_field.val() === this.default_text ? "" : e("<div/>").text(e.trim(this.search_field.val())).html(), o = this.search_contains ? "" : "^", s = new RegExp(o + l.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), "i"), p = new RegExp(l.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), "i"), y = this.results_data, d = 0, m = y.length; m > d; d++)
                if (n = y[d], !n.disabled && !n.empty)
                    if (n.group) e("#" + n.dom_id).css("display", "none");
                    else if (!this.is_multiple || !n.selected) {
                if (t = !1, a = n.dom_id, u = e("#" + a), s.test(n.html)) t = !0, f += 1;
                else if (this.enable_split_word_search && (n.html.indexOf(" ") >= 0 || 0 === n.html.indexOf("[")) && (i = n.html.replace(/\[|\]/g, "").split(" "), i.length))
                    for (v = 0, g = i.length; g > v; v++) r = i[v], s.test(r) && (t = !0, f += 1);
                t ? (l.length ? (c = n.html.search(p), h = n.html.substr(0, c + l.length) + "</em>" + n.html.substr(c + l.length), h = h.substr(0, c) + "<em>" + h.substr(c)) : h = n.html, u.html(h), this.result_activate(u), null != n.group_array_index && e("#" + this.results_data[n.group_array_index].dom_id).css("display", "list-item")) : (this.result_highlight && a === this.result_highlight.attr("id") && this.result_clear_highlight(), this.result_deactivate(u))
            }
            return 1 > f && l.length ? this.no_results(l) : this.winnow_results_set_highlight()
        }, i.prototype.winnow_results_clear = function () {
            var t, n, r, i, s;
            for (this.search_field.val(""), n = this.search_results.find("li"), s = [], r = 0, i = n.length; i > r; r++) t = n[r], t = e(t), t.hasClass("group-result") ? s.push(t.css("display", "auto")) : this.is_multiple && t.hasClass("result-selected") ? s.push(void 0) : s.push(this.result_activate(t));
            return s
        }, i.prototype.winnow_results_set_highlight = function () {
            var e, t;
            return this.result_highlight || (t = this.is_multiple ? [] : this.search_results.find(".result-selected.active-result"), e = t.length ? t.first() : this.search_results.find(".active-result").first(), null == e) ? void 0 : this.result_do_highlight(e)
        }, i.prototype.no_results = function (t) {
            var n;
            return n = e('<li class="no-results">' + this.results_none_found + ' "<span></span>"</li>'), n.find("span").first().html(t), this.search_results.append(n)
        }, i.prototype.no_results_clear = function () {
            return this.search_results.find(".no-results").remove()
        }, i.prototype.keydown_arrow = function () {
            var t, n;
            return this.result_highlight ? this.results_showing && (n = this.result_highlight.nextAll("li.active-result").first(), n && this.result_do_highlight(n)) : (t = this.search_results.find("li.active-result").first(), t && this.result_do_highlight(e(t))), this.results_showing ? void 0 : this.results_show()
        }, i.prototype.keyup_arrow = function () {
            var e;
            return this.results_showing || this.is_multiple ? this.result_highlight ? (e = this.result_highlight.prevAll("li.active-result"), e.length ? this.result_do_highlight(e.first()) : (this.choices > 0 && this.results_hide(), this.result_clear_highlight())) : void 0 : this.results_show()
        }, i.prototype.keydown_backstroke = function () {
            var e;
            return this.pending_backstroke ? (this.choice_destroy(this.pending_backstroke.find("a").first()), this.clear_backstroke()) : (e = this.search_container.siblings("li.search-choice").last(), e.length && !e.hasClass("search-choice-disabled") ? (this.pending_backstroke = e, this.single_backstroke_delete ? this.keydown_backstroke() : this.pending_backstroke.addClass("search-choice-focus")) : void 0)
        }, i.prototype.clear_backstroke = function () {
            return this.pending_backstroke && this.pending_backstroke.removeClass("search-choice-focus"), this.pending_backstroke = null
        }, i.prototype.keydown_checker = function (e) {
            var t, n;
            switch (t = null != (n = e.which) ? n : e.keyCode, this.search_field_scale(), 8 !== t && this.pending_backstroke && this.clear_backstroke(), t) {
            case 8:
                this.backstroke_length = this.search_field.val().length;
                break;
            case 9:
                this.results_showing && !this.is_multiple && this.result_select(e), this.mouse_on_container = !1;
                break;
            case 13:
                e.preventDefault();
                break;
            case 38:
                e.preventDefault(), this.keyup_arrow();
                break;
            case 40:
                this.keydown_arrow()
            }
        }, i.prototype.search_field_scale = function () {
            var t, n, r, i, s, o, u, a, f;
            if (this.is_multiple) {
                for (r = 0, u = 0, s = "position:absolute; left: -1000px; top: -1000px; display:none;", o = ["font-size", "font-style", "font-weight", "font-family", "line-height", "text-transform", "letter-spacing"], a = 0, f = o.length; f > a; a++) i = o[a], s += i + ":" + this.search_field.css(i) + ";";
                return n = e("<div />", {
                    style: s
                }), n.text(this.search_field.val()), e("body").append(n), u = n.width() + 25, n.remove(), u > this.f_width - 10 && (u = this.f_width - 10), this.search_field.css({
                    width: u + "px"
                }), t = this.container.height(), this.dropdown.css({
                    top: t + "px"
                })
            }
        }, i.prototype.generate_random_id = function () {
            var t;
            for (t = "sel" + this.generate_random_char() + this.generate_random_char() + this.generate_random_char(); e("#" + t).length > 0;) t += this.generate_random_char();
            return t
        }, i
    }(AbstractChosen), r.Chosen = t, n = function (e) {
        var t;
        return t = e.outerWidth() - e.width()
    }, r.get_side_border_padding = n
}.call(this),
function (a) {
    var c = [].slice,
        d = {};
    a.amplify = {
        publish: function (a) {
            var e, f, g, i, b = c.call(arguments, 1),
                h = 0;
            if (!d[a]) return !0;
            for (e = d[a].slice(), g = e.length; g > h && (f = e[h], i = f.callback.apply(f.context, b), i !== !1); h++);
            return i !== !1
        },
        subscribe: function (a, b, c, e) {
            3 === arguments.length && "number" == typeof c && (e = c, c = b, b = null), 2 === arguments.length && (c = b, b = null), e = e || 10;
            for (var i, f = 0, g = a.split(/\s/), h = g.length; h > f; f++) {
                a = g[f], i = !1, d[a] || (d[a] = []);
                for (var j = d[a].length - 1, k = {
                    callback: c,
                    context: b,
                    priority: e
                }; j >= 0; j--)
                    if (d[a][j].priority <= e) {
                        d[a].splice(j + 1, 0, k), i = !0;
                        break
                    }
                i || d[a].unshift(k)
            }
            return c
        },
        unsubscribe: function (a, b) {
            if (d[a])
                for (var c = d[a].length, e = 0; c > e; e++)
                    if (d[a][e].callback === b) {
                        d[a].splice(e, 1);
                        break
                    }
        }
    }
}(this),
function (a, b) {
    function e(a, e) {
        c.addType(a, function (f, g, h) {
            var i, j, k, l, m = g,
                n = (new Date).getTime();
            if (!f) {
                m = {}, l = [], k = 0;
                try {
                    for (f = e.length; f = e.key(k++);) d.test(f) && (j = JSON.parse(e.getItem(f)), j.expires && j.expires <= n ? l.push(f) : m[f.replace(d, "")] = j.data);
                    for (; f = l.pop();) e.removeItem(f)
                } catch (o) {}
                return m
            }
            if (f = "__amplify__" + f, g === b) {
                if (i = e.getItem(f), j = i ? JSON.parse(i) : {
                    expires: -1
                }, !(j.expires && j.expires <= n)) return j.data;
                e.removeItem(f)
            } else if (null === g) e.removeItem(f);
            else {
                j = JSON.stringify({
                    data: g,
                    expires: h.expires ? n + h.expires : null
                });
                try {
                    e.setItem(f, j)
                } catch (o) {
                    c[a]();
                    try {
                        e.setItem(f, j)
                    } catch (o) {
                        throw c.error()
                    }
                }
            }
            return m
        })
    }
    var c = a.store = function (a, b, d, e) {
        var e = c.type;
        return d && d.type && d.type in c.types && (e = d.type), c.types[e](a, b, d || {})
    };
    c.types = {}, c.type = null, c.addType = function (a, b) {
        c.type || (c.type = a), c.types[a] = b, c[a] = function (b, d, e) {
            return e = e || {}, e.type = a, c(b, d, e)
        }
    }, c.error = function () {
        return "amplify.store quota exceeded"
    };
    var d = /^__amplify__/;
    for (var f in {
        localStorage: 1,
        sessionStorage: 1
    }) try {
        window[f].getItem && e(f, window[f])
    } catch (g) {}
    if (window.globalStorage) try {
            e("globalStorage", window.globalStorage[window.location.hostname]), "sessionStorage" === c.type && (c.type = "globalStorage")
        } catch (g) {}! function () {
            if (!c.types.localStorage) {
                var a = document.createElement("div"),
                    d = "amplify";
                a.style.display = "none", document.getElementsByTagName("head")[0].appendChild(a);
                try {
                    a.addBehavior("#default#userdata"), a.load(d)
                } catch (e) {
                    return a.parentNode.removeChild(a), void 0
                }
                c.addType("userData", function (e, f, g) {
                    a.load(d);
                    var h, i, j, k, l, m = f,
                        n = (new Date).getTime();
                    if (!e) {
                        for (m = {}, l = [], k = 0; h = a.XMLDocument.documentElement.attributes[k++];) i = JSON.parse(h.value), i.expires && i.expires <= n ? l.push(h.name) : m[h.name] = i.data;
                        for (; e = l.pop();) a.removeAttribute(e);
                        return a.save(d), m
                    }
                    if (e = e.replace(/[^-._0-9A-Za-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u37f-\u1fff\u200c-\u200d\u203f\u2040\u2070-\u218f]/g, "-"), f === b) {
                        if (h = a.getAttribute(e), i = h ? JSON.parse(h) : {
                            expires: -1
                        }, !(i.expires && i.expires <= n)) return i.data;
                        a.removeAttribute(e)
                    } else null === f ? a.removeAttribute(e) : (j = a.getAttribute(e), i = JSON.stringify({
                        data: f,
                        expires: g.expires ? n + g.expires : null
                    }), a.setAttribute(e, i));
                    try {
                        a.save(d)
                    } catch (o) {
                        null === j ? a.removeAttribute(e) : a.setAttribute(e, j), c.userData();
                        try {
                            a.setAttribute(e, i), a.save(d)
                        } catch (o) {
                            throw null === j ? a.removeAttribute(e) : a.setAttribute(e, j), c.error()
                        }
                    }
                    return m
                })
            }
        }(),
        function () {
            function e(a) {
                return a === b ? b : JSON.parse(JSON.stringify(a))
            }
            var a = {},
                d = {};
            c.addType("memory", function (c, f, g) {
                return c ? f === b ? e(a[c]) : (d[c] && (clearTimeout(d[c]), delete d[c]), null === f ? (delete a[c], null) : (a[c] = f, g.expires && (d[c] = setTimeout(function () {
                    delete a[c], delete d[c]
                }, g.expires)), f)) : e(a)
            })
        }()
}(this.amplify = this.amplify || {}),
function (a) {
    function e(a) {
        var b = !1;
        return setTimeout(function () {
                b = !0
            }, 1),
            function () {
                var c = this,
                    d = arguments;
                b ? a.apply(c, d) : setTimeout(function () {
                    a.apply(c, d)
                }, 1)
            }
    }

    function d(a) {
        return "[object Function]" === {}.toString.call(a)
    }

    function c() {}
    a.request = function (b, f, g) {
        var h = b || {};
        "string" == typeof h && (d(f) && (g = f, f = {}), h = {
            resourceId: b,
            data: f || {},
            success: g
        });
        var i = {
                abort: c
            },
            j = a.request.resources[h.resourceId],
            k = h.success || c,
            l = h.error || c;
        if (h.success = e(function (b, c) {
            c = c || "success", a.publish("request.success", h, b, c), a.publish("request.complete", h, b, c), k(b, c)
        }), h.error = e(function (b, c) {
            c = c || "error", a.publish("request.error", h, b, c), a.publish("request.complete", h, b, c), l(b, c)
        }), !j) {
            if (!h.resourceId) throw "amplify.request: no resourceId provided";
            throw "amplify.request: unknown resourceId: " + h.resourceId
        }
        return a.publish("request.before", h) ? (a.request.resources[h.resourceId](h, i), i) : (h.error(null, "abort"), void 0)
    }, a.request.types = {}, a.request.resources = {}, a.request.define = function (b, c, d) {
        if ("string" == typeof c) {
            if (!(c in a.request.types)) throw "amplify.request.define: unknown type: " + c;
            d.resourceId = b, a.request.resources[b] = a.request.types[c](d)
        } else a.request.resources[b] = c
    }
}(amplify),
function (a, b, c) {
    var d = ["status", "statusText", "responseText", "responseXML", "readyState"],
        e = /\{([^\}]+)\}/g;
    a.request.types.ajax = function (e) {
        return e = b.extend({
                type: "GET"
            }, e),
            function (f, g) {
                function n(a, e) {
                    b.each(d, function (a, b) {
                        try {
                            m[b] = h[b]
                        } catch (c) {}
                    }), /OK$/.test(m.statusText) && (m.statusText = "success"), a === c && (a = null), l && (e = "abort"), /timeout|error|abort/.test(e) ? m.error(a, e) : m.success(a, e), n = b.noop
                }
                var h, j = (e.url, g.abort),
                    k = b.extend(!0, {}, e, {
                        data: f.data
                    }),
                    l = !1,
                    m = {
                        readyState: 0,
                        setRequestHeader: function (a, b) {
                            return h.setRequestHeader(a, b)
                        },
                        getAllResponseHeaders: function () {
                            return h.getAllResponseHeaders()
                        },
                        getResponseHeader: function (a) {
                            return h.getResponseHeader(a)
                        },
                        overrideMimeType: function (a) {
                            return h.overrideMideType(a)
                        },
                        abort: function () {
                            l = !0;
                            try {
                                h.abort()
                            } catch (a) {}
                            n(null, "abort")
                        },
                        success: function (a, b) {
                            f.success(a, b)
                        },
                        error: function (a, b) {
                            f.error(a, b)
                        }
                    };
                a.publish("request.ajax.preprocess", e, f, k, m), b.extend(k, {
                    success: function (a, b) {
                        n(a, b)
                    },
                    error: function (a, b) {
                        n(null, b)
                    },
                    beforeSend: function (b, c) {
                        h = b, k = c;
                        var d = e.beforeSend ? e.beforeSend.call(this, m, k) : !0;
                        return d && a.publish("request.before.ajax", e, f, k, m)
                    }
                }), b.ajax(k), g.abort = function () {
                    m.abort(), j.call(this)
                }
            }
    }, a.subscribe("request.ajax.preprocess", function (a, c, d) {
        var f = [],
            g = d.data;
        "string" != typeof g && (g = b.extend(!0, {}, a.data, g), d.url = d.url.replace(e, function (a, b) {
            return b in g ? (f.push(b), g[b]) : void 0
        }), b.each(f, function (a, b) {
            delete g[b]
        }), d.data = g)
    }), a.subscribe("request.ajax.preprocess", function (a, c, d) {
        var e = d.data,
            f = a.dataMap;
        !!f && "string" != typeof e && (b.isFunction(f) ? d.data = f(e) : (b.each(a.dataMap, function (a, b) {
            a in e && (e[b] = e[a], delete e[a])
        }), d.data = e))
    });
    var f = a.request.cache = {
        _key: function (a, b, c) {
            function g() {
                return c.charCodeAt(e++) << 24 | c.charCodeAt(e++) << 16 | c.charCodeAt(e++) << 8 | c.charCodeAt(e++) << 0
            }
            c = b + c;
            for (var d = c.length, e = 0, f = g(); d > e;) f ^= g();
            return "request-" + a + "-" + f
        },
        _default: function () {
            var a = {};
            return function (b, c, d, e) {
                var g = f._key(c.resourceId, d.url, d.data),
                    h = b.cache;
                if (g in a) return e.success(a[g]), !1;
                var i = e.success;
                e.success = function (b) {
                    a[g] = b, "number" == typeof h && setTimeout(function () {
                        delete a[g]
                    }, h), i.apply(this, arguments)
                }
            }
        }()
    };
    a.store && (b.each(a.store.types, function (b) {
        f[b] = function (c, d, e, g) {
            var h = f._key(d.resourceId, e.url, e.data),
                i = a.store[b](h);
            if (i) return e.success(i), !1;
            var j = g.success;
            g.success = function (d) {
                a.store[b](h, d, {
                    expires: c.cache.expires
                }), j.apply(this, arguments)
            }
        }
    }), f.persist = f[a.store.type]), a.subscribe("request.before.ajax", function (a) {
        var b = a.cache;
        return b ? (b = b.type || b, f[b in f ? b : "_default"].apply(this, arguments)) : void 0
    }), a.request.decoders = {
        jsend: function (a, b, c, d, e) {
            "success" === a.status ? d(a.data) : "fail" === a.status ? e(a.data, "fail") : "error" === a.status && (delete a.status, e(a, "error"))
        }
    }, a.subscribe("request.before.ajax", function (c, d, e, f) {
        function k(a, b) {
            h(a, b)
        }

        function j(a, b) {
            g(a, b)
        }
        var g = f.success,
            h = f.error,
            i = b.isFunction(c.decoder) ? c.decoder : c.decoder in a.request.decoders ? a.request.decoders[c.decoder] : a.request.decoders._default;
        !i || (f.success = function (a, b) {
            i(a, b, f, j, k)
        }, f.error = function (a, b) {
            i(a, b, f, j, k)
        })
    })
}(amplify, jQuery), ! function (t) {
    function e(t, e) {
        return function (n) {
            return u(t.call(this, n), e)
        }
    }

    function n(t, e) {
        return function (n) {
            return this.lang().ordinal(t.call(this, n), e)
        }
    }

    function s() {}

    function i(t) {
        a(this, t)
    }

    function r(t) {
        var e = t.years || t.year || t.y || 0,
            n = t.months || t.month || t.M || 0,
            s = t.weeks || t.week || t.w || 0,
            i = t.days || t.day || t.d || 0,
            r = t.hours || t.hour || t.h || 0,
            a = t.minutes || t.minute || t.m || 0,
            o = t.seconds || t.second || t.s || 0,
            u = t.milliseconds || t.millisecond || t.ms || 0;
        this._input = t, this._milliseconds = u + 1e3 * o + 6e4 * a + 36e5 * r, this._days = i + 7 * s, this._months = n + 12 * e, this._data = {}, this._bubble()
    }

    function a(t, e) {
        for (var n in e) e.hasOwnProperty(n) && (t[n] = e[n]);
        return t
    }

    function o(t) {
        return 0 > t ? Math.ceil(t) : Math.floor(t)
    }

    function u(t, e) {
        for (var n = t + ""; n.length < e;) n = "0" + n;
        return n
    }

    function h(t, e, n, s) {
        var i, r, a = e._milliseconds,
            o = e._days,
            u = e._months;
        a && t._d.setTime(+t._d + a * n), (o || u) && (i = t.minute(), r = t.hour()), o && t.date(t.date() + o * n), u && t.month(t.month() + u * n), a && !s && H.updateOffset(t), (o || u) && (t.minute(i), t.hour(r))
    }

    function d(t) {
        return "[object Array]" === Object.prototype.toString.call(t)
    }

    function c(t, e) {
        var n, s = Math.min(t.length, e.length),
            i = Math.abs(t.length - e.length),
            r = 0;
        for (n = 0; s > n; n++)~~ t[n] !== ~~e[n] && r++;
        return r + i
    }

    function f(t) {
        return t ? ie[t] || t.toLowerCase().replace(/(.)s$/, "$1") : t
    }

    function l(t, e) {
        return e.abbr = t, x[t] || (x[t] = new s), x[t].set(e), x[t]
    }

    function _(t) {
        if (!t) return H.fn._lang;
        if (!x[t] && A) try {
            require("./lang/" + t)
        } catch (e) {
            return H.fn._lang
        }
        return x[t]
    }

    function m(t) {
        return t.match(/\[.*\]/) ? t.replace(/^\[|\]$/g, "") : t.replace(/\\/g, "")
    }

    function y(t) {
        var e, n, s = t.match(E);
        for (e = 0, n = s.length; n > e; e++) s[e] = ue[s[e]] ? ue[s[e]] : m(s[e]);
        return function (i) {
            var r = "";
            for (e = 0; n > e; e++) r += s[e] instanceof Function ? s[e].call(i, t) : s[e];
            return r
        }
    }

    function M(t, e) {
        function n(e) {
            return t.lang().longDateFormat(e) || e
        }
        for (var s = 5; s-- && N.test(e);) e = e.replace(N, n);
        return re[e] || (re[e] = y(e)), re[e](t)
    }

    function g(t, e) {
        switch (t) {
        case "DDDD":
            return V;
        case "YYYY":
            return X;
        case "YYYYY":
            return $;
        case "S":
        case "SS":
        case "SSS":
        case "DDD":
            return I;
        case "MMM":
        case "MMMM":
        case "dd":
        case "ddd":
        case "dddd":
            return R;
        case "a":
        case "A":
            return _(e._l)._meridiemParse;
        case "X":
            return B;
        case "Z":
        case "ZZ":
            return j;
        case "T":
            return q;
        case "MM":
        case "DD":
        case "YY":
        case "HH":
        case "hh":
        case "mm":
        case "ss":
        case "M":
        case "D":
        case "d":
        case "H":
        case "h":
        case "m":
        case "s":
            return J;
        default:
            return new RegExp(t.replace("\\", ""))
        }
    }

    function p(t) {
        var e = (j.exec(t) || [])[0],
            n = (e + "").match(ee) || ["-", 0, 0],
            s = +(60 * n[1]) + ~~n[2];
        return "+" === n[0] ? -s : s
    }

    function D(t, e, n) {
        var s, i = n._a;
        switch (t) {
        case "M":
        case "MM":
            i[1] = null == e ? 0 : ~~e - 1;
            break;
        case "MMM":
        case "MMMM":
            s = _(n._l).monthsParse(e), null != s ? i[1] = s : n._isValid = !1;
            break;
        case "D":
        case "DD":
        case "DDD":
        case "DDDD":
            null != e && (i[2] = ~~e);
            break;
        case "YY":
            i[0] = ~~e + (~~e > 68 ? 1900 : 2e3);
            break;
        case "YYYY":
        case "YYYYY":
            i[0] = ~~e;
            break;
        case "a":
        case "A":
            n._isPm = _(n._l).isPM(e);
            break;
        case "H":
        case "HH":
        case "h":
        case "hh":
            i[3] = ~~e;
            break;
        case "m":
        case "mm":
            i[4] = ~~e;
            break;
        case "s":
        case "ss":
            i[5] = ~~e;
            break;
        case "S":
        case "SS":
        case "SSS":
            i[6] = ~~ (1e3 * ("0." + e));
            break;
        case "X":
            n._d = new Date(1e3 * parseFloat(e));
            break;
        case "Z":
        case "ZZ":
            n._useUTC = !0, n._tzm = p(e)
        }
        null == e && (n._isValid = !1)
    }

    function Y(t) {
        var e, n, s = [];
        if (!t._d) {
            for (e = 0; 7 > e; e++) t._a[e] = s[e] = null == t._a[e] ? 2 === e ? 1 : 0 : t._a[e];
            s[3] += ~~((t._tzm || 0) / 60), s[4] += ~~((t._tzm || 0) % 60), n = new Date(0), t._useUTC ? (n.setUTCFullYear(s[0], s[1], s[2]), n.setUTCHours(s[3], s[4], s[5], s[6])) : (n.setFullYear(s[0], s[1], s[2]), n.setHours(s[3], s[4], s[5], s[6])), t._d = n
        }
    }

    function w(t) {
        var e, n, s = t._f.match(E),
            i = t._i;
        for (t._a = [], e = 0; e < s.length; e++) n = (g(s[e], t).exec(i) || [])[0], n && (i = i.slice(i.indexOf(n) + n.length)), ue[s[e]] && D(s[e], n, t);
        i && (t._il = i), t._isPm && t._a[3] < 12 && (t._a[3] += 12), t._isPm === !1 && 12 === t._a[3] && (t._a[3] = 0), Y(t)
    }

    function k(t) {
        var e, n, s, r, o, u = 99;
        for (r = 0; r < t._f.length; r++) e = a({}, t), e._f = t._f[r], w(e), n = new i(e), o = c(e._a, n.toArray()), n._il && (o += n._il.length), u > o && (u = o, s = n);
        a(t, s)
    }

    function v(t) {
        var e, n = t._i,
            s = K.exec(n);
        if (s) {
            for (t._f = "YYYY-MM-DD" + (s[2] || " "), e = 0; 4 > e; e++)
                if (te[e][1].exec(n)) {
                    t._f += te[e][0];
                    break
                }
            j.exec(n) && (t._f += " Z"), w(t)
        } else t._d = new Date(n)
    }

    function T(e) {
        var n = e._i,
            s = G.exec(n);
        n === t ? e._d = new Date : s ? e._d = new Date(+s[1]) : "string" == typeof n ? v(e) : d(n) ? (e._a = n.slice(0), Y(e)) : e._d = n instanceof Date ? new Date(+n) : new Date(n)
    }

    function b(t, e, n, s, i) {
        return i.relativeTime(e || 1, !!n, t, s)
    }

    function S(t, e, n) {
        var s = W(Math.abs(t) / 1e3),
            i = W(s / 60),
            r = W(i / 60),
            a = W(r / 24),
            o = W(a / 365),
            u = 45 > s && ["s", s] || 1 === i && ["m"] || 45 > i && ["mm", i] || 1 === r && ["h"] || 22 > r && ["hh", r] || 1 === a && ["d"] || 25 >= a && ["dd", a] || 45 >= a && ["M"] || 345 > a && ["MM", W(a / 30)] || 1 === o && ["y"] || ["yy", o];
        return u[2] = e, u[3] = t > 0, u[4] = n, b.apply({}, u)
    }

    function F(t, e, n) {
        var s, i = n - e,
            r = n - t.day();
        return r > i && (r -= 7), i - 7 > r && (r += 7), s = H(t).add("d", r), {
            week: Math.ceil(s.dayOfYear() / 7),
            year: s.year()
        }
    }

    function O(t) {
        var e = t._i,
            n = t._f;
        return null === e || "" === e ? null : ("string" == typeof e && (t._i = e = _().preparse(e)), H.isMoment(e) ? (t = a({}, e), t._d = new Date(+e._d)) : n ? d(n) ? k(t) : w(t) : T(t), new i(t))
    }

    function z(t, e) {
        H.fn[t] = H.fn[t + "s"] = function (t) {
            var n = this._isUTC ? "UTC" : "";
            return null != t ? (this._d["set" + n + e](t), H.updateOffset(this), this) : this._d["get" + n + e]()
        }
    }

    function C(t) {
        H.duration.fn[t] = function () {
            return this._data[t]
        }
    }

    function L(t, e) {
        H.duration.fn["as" + t] = function () {
            return +this / e
        }
    }
    for (var H, P, U = "2.1.0", W = Math.round, x = {}, A = "undefined" != typeof module && module.exports, G = /^\/?Date\((\-?\d+)/i, Z = /(\-)?(\d*)?\.?(\d+)\:(\d+)\:(\d+)\.?(\d{3})?/, E = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g, N = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g, J = /\d\d?/, I = /\d{1,3}/, V = /\d{3}/, X = /\d{1,4}/, $ = /[+\-]?\d{1,6}/, R = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, j = /Z|[\+\-]\d\d:?\d\d/i, q = /T/i, B = /[\+\-]?\d+(\.\d{1,3})?/, K = /^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/, Q = "YYYY-MM-DDTHH:mm:ssZ", te = [
        ["HH:mm:ss.S", /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
        ["HH:mm:ss", /(T| )\d\d:\d\d:\d\d/],
        ["HH:mm", /(T| )\d\d:\d\d/],
        ["HH", /(T| )\d\d/]
    ], ee = /([\+\-]|\d\d)/gi, ne = "Date|Hours|Minutes|Seconds|Milliseconds".split("|"), se = {
        Milliseconds: 1,
        Seconds: 1e3,
        Minutes: 6e4,
        Hours: 36e5,
        Days: 864e5,
        Months: 2592e6,
        Years: 31536e6
    }, ie = {
        ms: "millisecond",
        s: "second",
        m: "minute",
        h: "hour",
        d: "day",
        w: "week",
        M: "month",
        y: "year"
    }, re = {}, ae = "DDD w W M D d".split(" "), oe = "M D H h m s w W".split(" "), ue = {
        M: function () {
            return this.month() + 1
        },
        MMM: function (t) {
            return this.lang().monthsShort(this, t)
        },
        MMMM: function (t) {
            return this.lang().months(this, t)
        },
        D: function () {
            return this.date()
        },
        DDD: function () {
            return this.dayOfYear()
        },
        d: function () {
            return this.day()
        },
        dd: function (t) {
            return this.lang().weekdaysMin(this, t)
        },
        ddd: function (t) {
            return this.lang().weekdaysShort(this, t)
        },
        dddd: function (t) {
            return this.lang().weekdays(this, t)
        },
        w: function () {
            return this.week()
        },
        W: function () {
            return this.isoWeek()
        },
        YY: function () {
            return u(this.year() % 100, 2)
        },
        YYYY: function () {
            return u(this.year(), 4)
        },
        YYYYY: function () {
            return u(this.year(), 5)
        },
        gg: function () {
            return u(this.weekYear() % 100, 2)
        },
        gggg: function () {
            return this.weekYear()
        },
        ggggg: function () {
            return u(this.weekYear(), 5)
        },
        GG: function () {
            return u(this.isoWeekYear() % 100, 2)
        },
        GGGG: function () {
            return this.isoWeekYear()
        },
        GGGGG: function () {
            return u(this.isoWeekYear(), 5)
        },
        e: function () {
            return this.weekday()
        },
        E: function () {
            return this.isoWeekday()
        },
        a: function () {
            return this.lang().meridiem(this.hours(), this.minutes(), !0)
        },
        A: function () {
            return this.lang().meridiem(this.hours(), this.minutes(), !1)
        },
        H: function () {
            return this.hours()
        },
        h: function () {
            return this.hours() % 12 || 12
        },
        m: function () {
            return this.minutes()
        },
        s: function () {
            return this.seconds()
        },
        S: function () {
            return~~ (this.milliseconds() / 100)
        },
        SS: function () {
            return u(~~(this.milliseconds() / 10), 2)
        },
        SSS: function () {
            return u(this.milliseconds(), 3)
        },
        Z: function () {
            var t = -this.zone(),
                e = "+";
            return 0 > t && (t = -t, e = "-"), e + u(~~(t / 60), 2) + ":" + u(~~t % 60, 2)
        },
        ZZ: function () {
            var t = -this.zone(),
                e = "+";
            return 0 > t && (t = -t, e = "-"), e + u(~~(10 * t / 6), 4)
        },
        z: function () {
            return this.zoneAbbr()
        },
        zz: function () {
            return this.zoneName()
        },
        X: function () {
            return this.unix()
        }
    }; ae.length;) P = ae.pop(), ue[P + "o"] = n(ue[P], P);
    for (; oe.length;) P = oe.pop(), ue[P + P] = e(ue[P], 2);
    for (ue.DDDD = e(ue.DDD, 3), s.prototype = {
        set: function (t) {
            var e, n;
            for (n in t) e = t[n], "function" == typeof e ? this[n] = e : this["_" + n] = e
        },
        _months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
        months: function (t) {
            return this._months[t.month()]
        },
        _monthsShort: "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
        monthsShort: function (t) {
            return this._monthsShort[t.month()]
        },
        monthsParse: function (t) {
            var e, n, s;
            for (this._monthsParse || (this._monthsParse = []), e = 0; 12 > e; e++)
                if (this._monthsParse[e] || (n = H([2e3, e]), s = "^" + this.months(n, "") + "|^" + this.monthsShort(n, ""), this._monthsParse[e] = new RegExp(s.replace(".", ""), "i")), this._monthsParse[e].test(t)) return e
        },
        _weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
        weekdays: function (t) {
            return this._weekdays[t.day()]
        },
        _weekdaysShort: "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
        weekdaysShort: function (t) {
            return this._weekdaysShort[t.day()]
        },
        _weekdaysMin: "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
        weekdaysMin: function (t) {
            return this._weekdaysMin[t.day()]
        },
        weekdaysParse: function (t) {
            var e, n, s;
            for (this._weekdaysParse || (this._weekdaysParse = []), e = 0; 7 > e; e++)
                if (this._weekdaysParse[e] || (n = H([2e3, 1]).day(e), s = "^" + this.weekdays(n, "") + "|^" + this.weekdaysShort(n, "") + "|^" + this.weekdaysMin(n, ""), this._weekdaysParse[e] = new RegExp(s.replace(".", ""), "i")), this._weekdaysParse[e].test(t)) return e
        },
        _longDateFormat: {
            LT: "h:mm A",
            L: "MM/DD/YYYY",
            LL: "MMMM D YYYY",
            LLL: "MMMM D YYYY LT",
            LLLL: "dddd, MMMM D YYYY LT"
        },
        longDateFormat: function (t) {
            var e = this._longDateFormat[t];
            return !e && this._longDateFormat[t.toUpperCase()] && (e = this._longDateFormat[t.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (t) {
                return t.slice(1)
            }), this._longDateFormat[t] = e), e
        },
        isPM: function (t) {
            return "p" === (t + "").toLowerCase()[0]
        },
        _meridiemParse: /[ap]\.?m?\.?/i,
        meridiem: function (t, e, n) {
            return t > 11 ? n ? "pm" : "PM" : n ? "am" : "AM"
        },
        _calendar: {
            sameDay: "[Today at] LT",
            nextDay: "[Tomorrow at] LT",
            nextWeek: "dddd [at] LT",
            lastDay: "[Yesterday at] LT",
            lastWeek: "[Last] dddd [at] LT",
            sameElse: "L"
        },
        calendar: function (t, e) {
            var n = this._calendar[t];
            return "function" == typeof n ? n.apply(e) : n
        },
        _relativeTime: {
            future: "in %s",
            past: "%s ago",
            s: "a few seconds",
            m: "a minute",
            mm: "%d minutes",
            h: "an hour",
            hh: "%d hours",
            d: "a day",
            dd: "%d days",
            M: "a month",
            MM: "%d months",
            y: "a year",
            yy: "%d years"
        },
        relativeTime: function (t, e, n, s) {
            var i = this._relativeTime[n];
            return "function" == typeof i ? i(t, e, n, s) : i.replace(/%d/i, t)
        },
        pastFuture: function (t, e) {
            var n = this._relativeTime[t > 0 ? "future" : "past"];
            return "function" == typeof n ? n(e) : n.replace(/%s/i, e)
        },
        ordinal: function (t) {
            return this._ordinal.replace("%d", t)
        },
        _ordinal: "%d",
        preparse: function (t) {
            return t
        },
        postformat: function (t) {
            return t
        },
        week: function (t) {
            return F(t, this._week.dow, this._week.doy).week
        },
        _week: {
            dow: 0,
            doy: 6
        }
    }, H = function (t, e, n) {
        return O({
            _i: t,
            _f: e,
            _l: n,
            _isUTC: !1
        })
    }, H.utc = function (t, e, n) {
        return O({
            _useUTC: !0,
            _isUTC: !0,
            _l: n,
            _i: t,
            _f: e
        })
    }, H.unix = function (t) {
        return H(1e3 * t)
    }, H.duration = function (t, e) {
        var n, s, i = H.isDuration(t),
            a = "number" == typeof t,
            o = i ? t._input : a ? {} : t,
            u = Z.exec(t);
        return a ? e ? o[e] = t : o.milliseconds = t : u && (n = "-" === u[1] ? -1 : 1, o = {
            y: 0,
            d: ~~u[2] * n,
            h: ~~u[3] * n,
            m: ~~u[4] * n,
            s: ~~u[5] * n,
            ms: ~~u[6] * n
        }), s = new r(o), i && t.hasOwnProperty("_lang") && (s._lang = t._lang), s
    }, H.version = U, H.defaultFormat = Q, H.updateOffset = function () {}, H.lang = function (t, e) {
        return t ? (e ? l(t, e) : x[t] || _(t), H.duration.fn._lang = H.fn._lang = _(t), void 0) : H.fn._lang._abbr
    }, H.langData = function (t) {
        return t && t._lang && t._lang._abbr && (t = t._lang._abbr), _(t)
    }, H.isMoment = function (t) {
        return t instanceof i
    }, H.isDuration = function (t) {
        return t instanceof r
    }, H.fn = i.prototype = {
        clone: function () {
            return H(this)
        },
        valueOf: function () {
            return +this._d + 6e4 * (this._offset || 0)
        },
        unix: function () {
            return Math.floor(+this / 1e3)
        },
        toString: function () {
            return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")
        },
        toDate: function () {
            return this._offset ? new Date(+this) : this._d
        },
        toISOString: function () {
            return M(H(this).utc(), "YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")
        },
        toArray: function () {
            var t = this;
            return [t.year(), t.month(), t.date(), t.hours(), t.minutes(), t.seconds(), t.milliseconds()]
        },
        isValid: function () {
            return null == this._isValid && (this._isValid = this._a ? !c(this._a, (this._isUTC ? H.utc(this._a) : H(this._a)).toArray()) : !isNaN(this._d.getTime())), !!this._isValid
        },
        utc: function () {
            return this.zone(0)
        },
        local: function () {
            return this.zone(0), this._isUTC = !1, this
        },
        format: function (t) {
            var e = M(this, t || H.defaultFormat);
            return this.lang().postformat(e)
        },
        add: function (t, e) {
            var n;
            return n = "string" == typeof t ? H.duration(+e, t) : H.duration(t, e), h(this, n, 1), this
        },
        subtract: function (t, e) {
            var n;
            return n = "string" == typeof t ? H.duration(+e, t) : H.duration(t, e), h(this, n, -1), this
        },
        diff: function (t, e, n) {
            var s, i, r = this._isUTC ? H(t).zone(this._offset || 0) : H(t).local(),
                a = 6e4 * (this.zone() - r.zone());
            return e = f(e), "year" === e || "month" === e ? (s = 432e5 * (this.daysInMonth() + r.daysInMonth()), i = 12 * (this.year() - r.year()) + (this.month() - r.month()), i += (this - H(this).startOf("month") - (r - H(r).startOf("month"))) / s, i -= 6e4 * (this.zone() - H(this).startOf("month").zone() - (r.zone() - H(r).startOf("month").zone())) / s, "year" === e && (i /= 12)) : (s = this - r, i = "second" === e ? s / 1e3 : "minute" === e ? s / 6e4 : "hour" === e ? s / 36e5 : "day" === e ? (s - a) / 864e5 : "week" === e ? (s - a) / 6048e5 : s), n ? i : o(i)
        },
        from: function (t, e) {
            return H.duration(this.diff(t)).lang(this.lang()._abbr).humanize(!e)
        },
        fromNow: function (t) {
            return this.from(H(), t)
        },
        calendar: function () {
            var t = this.diff(H().startOf("day"), "days", !0),
                e = -6 > t ? "sameElse" : -1 > t ? "lastWeek" : 0 > t ? "lastDay" : 1 > t ? "sameDay" : 2 > t ? "nextDay" : 7 > t ? "nextWeek" : "sameElse";
            return this.format(this.lang().calendar(e, this))
        },
        isLeapYear: function () {
            var t = this.year();
            return 0 === t % 4 && 0 !== t % 100 || 0 === t % 400
        },
        isDST: function () {
            return this.zone() < this.clone().month(0).zone() || this.zone() < this.clone().month(5).zone()
        },
        day: function (t) {
            var e = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
            return null != t ? "string" == typeof t && (t = this.lang().weekdaysParse(t), "number" != typeof t) ? this : this.add({
                d: t - e
            }) : e
        },
        month: function (t) {
            var e, n = this._isUTC ? "UTC" : "";
            return null != t ? "string" == typeof t && (t = this.lang().monthsParse(t), "number" != typeof t) ? this : (e = this.date(), this.date(1), this._d["set" + n + "Month"](t), this.date(Math.min(e, this.daysInMonth())), H.updateOffset(this), this) : this._d["get" + n + "Month"]()
        },
        startOf: function (t) {
            switch (t = f(t)) {
            case "year":
                this.month(0);
            case "month":
                this.date(1);
            case "week":
            case "day":
                this.hours(0);
            case "hour":
                this.minutes(0);
            case "minute":
                this.seconds(0);
            case "second":
                this.milliseconds(0)
            }
            return "week" === t && this.weekday(0), this
        },
        endOf: function (t) {
            return this.startOf(t).add(t, 1).subtract("ms", 1)
        },
        isAfter: function (t, e) {
            return e = "undefined" != typeof e ? e : "millisecond", +this.clone().startOf(e) > +H(t).startOf(e)
        },
        isBefore: function (t, e) {
            return e = "undefined" != typeof e ? e : "millisecond", +this.clone().startOf(e) < +H(t).startOf(e)
        },
        isSame: function (t, e) {
            return e = "undefined" != typeof e ? e : "millisecond", +this.clone().startOf(e) === +H(t).startOf(e)
        },
        min: function (t) {
            return t = H.apply(null, arguments), this > t ? this : t
        },
        max: function (t) {
            return t = H.apply(null, arguments), t > this ? this : t
        },
        zone: function (t) {
            var e = this._offset || 0;
            return null == t ? this._isUTC ? e : this._d.getTimezoneOffset() : ("string" == typeof t && (t = p(t)), Math.abs(t) < 16 && (t = 60 * t), this._offset = t, this._isUTC = !0, e !== t && h(this, H.duration(e - t, "m"), 1, !0), this)
        },
        zoneAbbr: function () {
            return this._isUTC ? "UTC" : ""
        },
        zoneName: function () {
            return this._isUTC ? "Coordinated Universal Time" : ""
        },
        daysInMonth: function () {
            return H.utc([this.year(), this.month() + 1, 0]).date()
        },
        dayOfYear: function (t) {
            var e = W((H(this).startOf("day") - H(this).startOf("year")) / 864e5) + 1;
            return null == t ? e : this.add("d", t - e)
        },
        weekYear: function (t) {
            var e = F(this, this.lang()._week.dow, this.lang()._week.doy).year;
            return null == t ? e : this.add("y", t - e)
        },
        isoWeekYear: function (t) {
            var e = F(this, 1, 4).year;
            return null == t ? e : this.add("y", t - e)
        },
        week: function (t) {
            var e = this.lang().week(this);
            return null == t ? e : this.add("d", 7 * (t - e))
        },
        isoWeek: function (t) {
            var e = F(this, 1, 4).week;
            return null == t ? e : this.add("d", 7 * (t - e))
        },
        weekday: function (t) {
            var e = (this._d.getDay() + 7 - this.lang()._week.dow) % 7;
            return null == t ? e : this.add("d", t - e)
        },
        isoWeekday: function (t) {
            return null == t ? this.day() || 7 : this.day(this.day() % 7 ? t : t - 7)
        },
        lang: function (e) {
            return e === t ? this._lang : (this._lang = _(e), this)
        }
    }, P = 0; P < ne.length; P++) z(ne[P].toLowerCase().replace(/s$/, ""), ne[P]);
    z("year", "FullYear"), H.fn.days = H.fn.day, H.fn.months = H.fn.month, H.fn.weeks = H.fn.week, H.fn.isoWeeks = H.fn.isoWeek, H.fn.toJSON = H.fn.toISOString, H.duration.fn = r.prototype = {
        _bubble: function () {
            var t, e, n, s, i = this._milliseconds,
                r = this._days,
                a = this._months,
                u = this._data;
            u.milliseconds = i % 1e3, t = o(i / 1e3), u.seconds = t % 60, e = o(t / 60), u.minutes = e % 60, n = o(e / 60), u.hours = n % 24, r += o(n / 24), u.days = r % 30, a += o(r / 30), u.months = a % 12, s = o(a / 12), u.years = s
        },
        weeks: function () {
            return o(this.days() / 7)
        },
        valueOf: function () {
            return this._milliseconds + 864e5 * this._days + 2592e6 * (this._months % 12) + 31536e6 * ~~(this._months / 12)
        },
        humanize: function (t) {
            var e = +this,
                n = S(e, !t, this.lang());
            return t && (n = this.lang().pastFuture(e, n)), this.lang().postformat(n)
        },
        add: function (t, e) {
            var n = H.duration(t, e);
            return this._milliseconds += n._milliseconds, this._days += n._days, this._months += n._months, this._bubble(), this
        },
        subtract: function (t, e) {
            var n = H.duration(t, e);
            return this._milliseconds -= n._milliseconds, this._days -= n._days, this._months -= n._months, this._bubble(), this
        },
        get: function (t) {
            return t = f(t), this[t.toLowerCase() + "s"]()
        },
        as: function (t) {
            return t = f(t), this["as" + t.charAt(0).toUpperCase() + t.slice(1) + "s"]()
        },
        lang: H.fn.lang
    };
    for (P in se) se.hasOwnProperty(P) && (L(P, se[P]), C(P.toLowerCase()));
    L("Weeks", 6048e5), H.duration.fn.asMonths = function () {
        return (+this - 31536e6 * this.years()) / 2592e6 + 12 * this.years()
    }, H.lang("en", {
        ordinal: function (t) {
            var e = t % 10,
                n = 1 === ~~(t % 100 / 10) ? "th" : 1 === e ? "st" : 2 === e ? "nd" : 3 === e ? "rd" : "th";
            return t + n
        }
    }), A && (module.exports = H), "undefined" == typeof ender && (this.moment = H), "function" == typeof define && define.amd && define("moment", [], function () {
        return H
    })
}.call(this);
var XDate = function (g, m, A, p) {
        function f() {
            var d, a = this instanceof f ? this : new f,
                c = arguments,
                b = c.length;
            if ("boolean" == typeof c[b - 1] && (d = c[--b], c = q(c, 0, b)), b)
                if (1 == b) {
                    if (b = c[0], b instanceof g || "number" == typeof b) a[0] = new g(+b);
                    else if (b instanceof f) {
                        var c = a,
                            h = new g(+b[0]);
                        l(b) && (h.toString = w), c[0] = h
                    } else if ("string" == typeof b) {
                        a[0] = new g(0);
                        a: {
                            for (var e, c = b, b = d || !1, h = f.parsers, r = 0; r < h.length; r++)
                                if (e = h[r](c, b, a)) {
                                    a = e;
                                    break a
                                }
                            a[0] = new g(c)
                        }
                    }
                } else a[0] = new g(n.apply(g, c)), d || (a[0] = s(a[0]));
            else a[0] = new g;
            return "boolean" == typeof d && B(a, d), a
        }

        function l(a) {
            return a[0].toString === w
        }

        function B(a, c, b) {
            return c ? l(a) || (b && (a[0] = new g(n(a[0].getFullYear(), a[0].getMonth(), a[0].getDate(), a[0].getHours(), a[0].getMinutes(), a[0].getSeconds(), a[0].getMilliseconds()))), a[0].toString = w) : l(a) && (a[0] = b ? s(a[0]) : new g(+a[0])), a
        }

        function C(a, c, b, d, h) {
            var e = k(j, a[0], h),
                a = k(D, a[0], h),
                h = 1 == c ? b % 12 : e(1),
                f = !1;
            2 == d.length && "boolean" == typeof d[1] && (f = d[1], d = [b]), a(c, d), f && e(1) != h && (a(1, [e(1) - 1]), a(2, [E(e(0), e(1))]))
        }

        function F(a, c, b, d) {
            var b = Number(b),
                h = m.floor(b);
            a["set" + o[c]](a["get" + o[c]]() + h, d || !1), h != b && 6 > c && F(a, c + 1, (b - h) * G[c], d)
        }

        function H(a, c, b) {
            var a = a.clone().setUTCMode(!0, !0),
                c = f(c).setUTCMode(!0, !0),
                d = 0;
            if (0 == b || 1 == b) {
                for (var h = 6; h >= b; h--) d /= G[h], d += j(c, !1, h) - j(a, !1, h);
                1 == b && (d += 12 * (c.getFullYear() - a.getFullYear()))
            } else 2 == b ? (b = a.toDate().setUTCHours(0, 0, 0, 0), d = c.toDate().setUTCHours(0, 0, 0, 0), d = m.round((d - b) / 864e5) + (c - d - (a - b)) / 864e5) : d = (c - a) / [36e5, 6e4, 1e3, 1][b - 3];
            return d
        }

        function t(a) {
            var c = a(0),
                b = a(1),
                a = a(2),
                b = new g(n(c, b, a)),
                d = u(c),
                a = d;
            return d > b ? a = u(c - 1) : (c = u(c + 1), b >= c && (a = c)), m.floor(m.round((b - a) / 864e5) / 7) + 1
        }

        function u(a) {
            return a = new g(n(a, 0, 4)), a.setUTCDate(a.getUTCDate() - (a.getUTCDay() + 6) % 7), a
        }

        function I(a, c, b, d) {
            var h = k(j, a, d),
                e = k(D, a, d),
                b = u(b === p ? h(0) : b);
            d || (b = s(b)), a.setTime(+b), e(2, [h(2) + 7 * (c - 1)])
        }

        function J(a, c, b, d, e) {
            var r = f.locales,
                g = r[f.defaultLocale] || {},
                i = k(j, a, e),
                b = ("string" == typeof b ? r[b] : b) || {};
            return x(a, c, function (a) {
                if (d)
                    for (var b = (7 == a ? 2 : a) - 1; b >= 0; b--) d.push(i(b));
                return i(a)
            }, function (a) {
                return b[a] || g[a]
            }, e)
        }

        function x(a, c, b, d, e) {
            for (var f, g, i = ""; f = c.match(M);) {
                if (i += c.substr(0, f.index), f[1]) {
                    g = i;
                    for (var i = a, j = f[1], l = b, m = d, n = e, k = j.length, o = void 0, q = ""; k > 0;) o = N(i, j.substr(0, k), l, m, n), o !== p ? (q += o, j = j.substr(k), k = j.length) : k--;
                    i = g + (q + j)
                } else f[3] ? (g = x(a, f[4], b, d, e), parseInt(g.replace(/\D/g, ""), 10) && (i += g)) : i += f[7] || "'";
                c = c.substr(f.index + f[0].length)
            }
            return i + c
        }

        function N(a, c, b, d, e) {
            var g = f.formatters[c];
            if ("string" == typeof g) return x(a, g, b, d, e);
            if ("function" == typeof g) return g(a, e || !1, d);
            switch (c) {
            case "fff":
                return i(b(6), 3);
            case "s":
                return b(5);
            case "ss":
                return i(b(5));
            case "m":
                return b(4);
            case "mm":
                return i(b(4));
            case "h":
                return b(3) % 12 || 12;
            case "hh":
                return i(b(3) % 12 || 12);
            case "H":
                return b(3);
            case "HH":
                return i(b(3));
            case "d":
                return b(2);
            case "dd":
                return i(b(2));
            case "ddd":
                return d("dayNamesShort")[b(7)] || "";
            case "dddd":
                return d("dayNames")[b(7)] || "";
            case "M":
                return b(1) + 1;
            case "MM":
                return i(b(1) + 1);
            case "MMM":
                return d("monthNamesShort")[b(1)] || "";
            case "MMMM":
                return d("monthNames")[b(1)] || "";
            case "yy":
                return (b(0) + "").substring(2);
            case "yyyy":
                return b(0);
            case "t":
                return v(b, d).substr(0, 1).toLowerCase();
            case "tt":
                return v(b, d).toLowerCase();
            case "T":
                return v(b, d).substr(0, 1);
            case "TT":
                return v(b, d);
            case "z":
            case "zz":
            case "zzz":
                return e ? c = "Z" : (d = a.getTimezoneOffset(), a = 0 > d ? "+" : "-", b = m.floor(m.abs(d) / 60), d = m.abs(d) % 60, e = b, "zz" == c ? e = i(b) : "zzz" == c && (e = i(b) + ":" + i(d)), c = a + e), c;
            case "w":
                return t(b);
            case "ww":
                return i(t(b));
            case "S":
                return c = b(2), c > 10 && 20 > c ? "th" : ["st", "nd", "rd"][c % 10 - 1] || "th"
            }
        }

        function v(a, c) {
            return a(3) < 12 ? c("amDesignator") : c("pmDesignator")
        }

        function y(a) {
            return !isNaN(+a[0])
        }

        function j(a, c, b) {
            return a["get" + (c ? "UTC" : "") + o[b]]()
        }

        function D(a, c, b, d) {
            a["set" + (c ? "UTC" : "") + o[b]].apply(a, d)
        }

        function s(a) {
            return new g(a.getUTCFullYear(), a.getUTCMonth(), a.getUTCDate(), a.getUTCHours(), a.getUTCMinutes(), a.getUTCSeconds(), a.getUTCMilliseconds())
        }

        function E(a, c) {
            return 32 - new g(n(a, c, 32)).getUTCDate()
        }

        function z(a) {
            return function () {
                return a.apply(p, [this].concat(q(arguments)))
            }
        }

        function k(a) {
            var c = q(arguments, 1);
            return function () {
                return a.apply(p, c.concat(q(arguments)))
            }
        }

        function q(a, c, b) {
            return A.prototype.slice.call(a, c || 0, b === p ? a.length : b)
        }

        function K(a, c) {
            for (var b = 0; b < a.length; b++) c(a[b], b)
        }

        function i(a, c) {
            for (c = c || 2, a += ""; a.length < c;) a = "0" + a;
            return a
        }
        var o = "FullYear,Month,Date,Hours,Minutes,Seconds,Milliseconds,Day,Year".split(","),
            L = ["Years", "Months", "Days"],
            G = [12, 31, 24, 60, 60, 1e3, 1],
            M = /(([a-zA-Z])\2*)|(\((('.*?'|\(.*?\)|.)*?)\))|('(.*?)')/,
            n = g.UTC,
            w = g.prototype.toUTCString,
            e = f.prototype;
        return e.length = 1, e.splice = A.prototype.splice, e.getUTCMode = z(l), e.setUTCMode = z(B), e.getTimezoneOffset = function () {
            return l(this) ? 0 : this[0].getTimezoneOffset()
        }, K(o, function (a, c) {
            e["get" + a] = function () {
                return j(this[0], l(this), c)
            }, 8 != c && (e["getUTC" + a] = function () {
                return j(this[0], !0, c)
            }), 7 != c && (e["set" + a] = function (a) {
                return C(this, c, a, arguments, l(this)), this
            }, 8 != c && (e["setUTC" + a] = function (a) {
                return C(this, c, a, arguments, !0), this
            }, e["add" + (L[c] || a)] = function (a, d) {
                return F(this, c, a, d), this
            }, e["diff" + (L[c] || a)] = function (a) {
                return H(this, a, c)
            }))
        }), e.getWeek = function () {
            return t(k(j, this, !1))
        }, e.getUTCWeek = function () {
            return t(k(j, this, !0))
        }, e.setWeek = function (a, c) {
            return I(this, a, c, !1), this
        }, e.setUTCWeek = function (a, c) {
            return I(this, a, c, !0), this
        }, e.addWeeks = function (a) {
            return this.addDays(7 * Number(a))
        }, e.diffWeeks = function (a) {
            return H(this, a, 2) / 7
        }, f.parsers = [
            function (a, c, b) {
                if (a = a.match(/^(\d{4})(-(\d{2})(-(\d{2})([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/)) {
                    var d = new g(n(a[1], a[3] ? a[3] - 1 : 0, a[5] || 1, a[7] || 0, a[8] || 0, a[10] || 0, a[12] ? 1e3 * Number("0." + a[12]) : 0));
                    return a[13] ? a[14] && d.setUTCMinutes(d.getUTCMinutes() + ("-" == a[15] ? 1 : -1) * (60 * Number(a[16]) + (a[18] ? Number(a[18]) : 0))) : c || (d = s(d)), b.setTime(+d)
                }
            }
        ], f.parse = function (a) {
            return +f("" + a)
        }, e.toString = function (a, c, b) {
            return a !== p && y(this) ? J(this, a, c, b, l(this)) : this[0].toString()
        }, e.toUTCString = e.toGMTString = function (a, c, b) {
            return a !== p && y(this) ? J(this, a, c, b, !0) : this[0].toUTCString()
        }, e.toISOString = function () {
            return this.toUTCString("yyyy-MM-dd'T'HH:mm:ss(.fff)zzz")
        }, f.defaultLocale = "", f.locales = {
            "": {
                monthNames: "January,February,March,April,May,June,July,August,September,October,November,December".split(","),
                monthNamesShort: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(","),
                dayNames: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(","),
                dayNamesShort: "Sun,Mon,Tue,Wed,Thu,Fri,Sat".split(","),
                amDesignator: "AM",
                pmDesignator: "PM"
            }
        }, f.formatters = {
            i: "yyyy-MM-dd'T'HH:mm:ss(.fff)",
            u: "yyyy-MM-dd'T'HH:mm:ss(.fff)zzz"
        }, K("getTime,valueOf,toDateString,toTimeString,toLocaleString,toLocaleDateString,toLocaleTimeString,toJSON".split(","), function (a) {
            e[a] = function () {
                return this[0][a]()
            }
        }), e.setTime = function (a) {
            return this[0].setTime(a), this
        }, e.valid = z(y), e.clone = function () {
            return new f(this)
        }, e.clearTime = function () {
            return this.setHours(0, 0, 0, 0)
        }, e.toDate = function () {
            return new g(+this[0])
        }, f.now = function () {
            return +new g
        }, f.today = function () {
            return (new f).clearTime()
        }, f.UTC = n, f.getDaysInMonth = E, "undefined" != typeof module && module.exports && (module.exports = f), f
    }(Date, Math, Array),
    Channel = function () {
        "use strict";

        function s_addBoundChan(win, origin, scope, handler) {
            function hasWin(arr) {
                for (var i = 0; i < arr.length; i++)
                    if (arr[i].win === win) return !0;
                return !1
            }
            var exists = !1;
            if ("*" === origin) {
                for (var k in s_boundChans)
                    if (s_boundChans.hasOwnProperty(k) && "*" !== k && "object" == typeof s_boundChans[k][scope] && (exists = hasWin(s_boundChans[k][scope]))) break
            } else s_boundChans["*"] && s_boundChans["*"][scope] && (exists = hasWin(s_boundChans["*"][scope])), !exists && s_boundChans[origin] && s_boundChans[origin][scope] && (exists = hasWin(s_boundChans[origin][scope])); if (exists) throw "A channel is already bound to the same window which overlaps with origin '" + origin + "' and has scope '" + scope + "'";
            "object" != typeof s_boundChans[origin] && (s_boundChans[origin] = {}), "object" != typeof s_boundChans[origin][scope] && (s_boundChans[origin][scope] = []), s_boundChans[origin][scope].push({
                win: win,
                handler: handler
            })
        }

        function s_removeBoundChan(win, origin, scope) {
            for (var arr = s_boundChans[origin][scope], i = 0; i < arr.length; i++) arr[i].win === win && arr.splice(i, 1);
            0 === s_boundChans[origin][scope].length && delete s_boundChans[origin][scope]
        }

        function s_isArray(obj) {
            return Array.isArray ? Array.isArray(obj) : -1 != obj.constructor.toString().indexOf("Array")
        }
        var s_curTranId = Math.floor(1000001 * Math.random()),
            s_boundChans = {},
            s_transIds = {},
            s_onMessage = function (e) {
                try {
                    var m = JSON.parse(e.data);
                    if ("object" != typeof m || null === m) throw "malformed"
                } catch (e) {
                    return
                }
                var s, i, meth, w = e.source,
                    o = e.origin;
                if ("string" == typeof m.method) {
                    var ar = m.method.split("::");
                    2 == ar.length ? (s = ar[0], meth = ar[1]) : meth = m.method
                }
                if ("undefined" != typeof m.id && (i = m.id), "string" == typeof meth) {
                    var delivered = !1;
                    if (s_boundChans[o] && s_boundChans[o][s])
                        for (var j = 0; j < s_boundChans[o][s].length; j++)
                            if (s_boundChans[o][s][j].win === w) {
                                s_boundChans[o][s][j].handler(o, meth, m), delivered = !0;
                                break
                            }
                    if (!delivered && s_boundChans["*"] && s_boundChans["*"][s])
                        for (var j = 0; j < s_boundChans["*"][s].length; j++)
                            if (s_boundChans["*"][s][j].win === w) {
                                s_boundChans["*"][s][j].handler(o, meth, m);
                                break
                            }
                } else "undefined" != typeof i && s_transIds[i] && s_transIds[i](o, meth, m)
            };
        return window.addEventListener ? window.addEventListener("message", s_onMessage, !1) : window.attachEvent && window.attachEvent("onmessage", s_onMessage), {
            build: function (cfg) {
                var debug = function (m) {
                    if (cfg.debugOutput && window.console && window.console.log) {
                        try {
                            "string" != typeof m && (m = JSON.stringify(m))
                        } catch (e) {}
                        console.log("[" + chanId + "] " + m)
                    }
                };
                if (!window.postMessage) throw "jschannel cannot run this browser, no postMessage";
                if (!window.JSON || !window.JSON.stringify || !window.JSON.parse) throw "jschannel cannot run this browser, no JSON parsing/serialization";
                if ("object" != typeof cfg) throw "Channel build invoked without a proper object argument";
                if (!cfg.window || !cfg.window.postMessage) throw "Channel.build() called without a valid window argument";
                if (window === cfg.window) throw "target window is same as present window -- not allowed";
                var validOrigin = !1;
                if ("string" == typeof cfg.origin) {
                    var oMatch;
                    "*" === cfg.origin ? validOrigin = !0 : null !== (oMatch = cfg.origin.match(/^https?:\/\/(?:[-a-zA-Z0-9_\.])+(?::\d+)?/)) && (cfg.origin = oMatch[0].toLowerCase(), validOrigin = !0)
                }
                if (!validOrigin) throw "Channel.build() called with an invalid origin";
                if ("undefined" != typeof cfg.scope) {
                    if ("string" != typeof cfg.scope) throw "scope, when specified, must be a string";
                    if (cfg.scope.split("::").length > 1) throw "scope may not contain double colons: '::'"
                }
                var chanId = function () {
                        for (var text = "", alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", i = 0; 5 > i; i++) text += alpha.charAt(Math.floor(Math.random() * alpha.length));
                        return text
                    }(),
                    regTbl = {},
                    outTbl = {},
                    inTbl = {},
                    ready = !1,
                    pendingQueue = [],
                    createTransaction = function (id, origin, callbacks) {
                        var shouldDelayReturn = !1,
                            completed = !1;
                        return {
                            origin: origin,
                            invoke: function (cbName, v) {
                                if (!inTbl[id]) throw "attempting to invoke a callback of a nonexistent transaction: " + id;
                                for (var valid = !1, i = 0; i < callbacks.length; i++)
                                    if (cbName === callbacks[i]) {
                                        valid = !0;
                                        break
                                    }
                                if (!valid) throw "request supports no such callback '" + cbName + "'";
                                postMessage({
                                    id: id,
                                    callback: cbName,
                                    params: v
                                })
                            },
                            error: function (error, message) {
                                if (completed = !0, !inTbl[id]) throw "error called for nonexistent message: " + id;
                                delete inTbl[id], postMessage({
                                    id: id,
                                    error: error,
                                    message: message
                                })
                            },
                            complete: function (v) {
                                if (completed = !0, !inTbl[id]) throw "complete called for nonexistent message: " + id;
                                delete inTbl[id], postMessage({
                                    id: id,
                                    result: v
                                })
                            },
                            delayReturn: function (delay) {
                                return "boolean" == typeof delay && (shouldDelayReturn = delay === !0), shouldDelayReturn
                            },
                            completed: function () {
                                return completed
                            }
                        }
                    },
                    setTransactionTimeout = function (transId, timeout, method) {
                        return window.setTimeout(function () {
                            if (outTbl[transId]) {
                                var msg = "timeout (" + timeout + "ms) exceeded on method '" + method + "'";
                                outTbl[transId].error("timeout_error", msg), delete outTbl[transId], delete s_transIds[transId]
                            }
                        }, timeout)
                    },
                    onMessage = function (origin, method, m) {
                        if ("function" == typeof cfg.gotMessageObserver) try {
                            cfg.gotMessageObserver(origin, m)
                        } catch (e) {
                            debug("gotMessageObserver() raised an exception: " + e.toString())
                        }
                        if (m.id && method) {
                            if (regTbl[method]) {
                                var trans = createTransaction(m.id, origin, m.callbacks ? m.callbacks : []);
                                inTbl[m.id] = {};
                                try {
                                    if (m.callbacks && s_isArray(m.callbacks) && m.callbacks.length > 0)
                                        for (var i = 0; i < m.callbacks.length; i++) {
                                            for (var path = m.callbacks[i], obj = m.params, pathItems = path.split("/"), j = 0; j < pathItems.length - 1; j++) {
                                                var cp = pathItems[j];
                                                "object" != typeof obj[cp] && (obj[cp] = {}), obj = obj[cp]
                                            }
                                            obj[pathItems[pathItems.length - 1]] = function () {
                                                var cbName = path;
                                                return function (params) {
                                                    return trans.invoke(cbName, params)
                                                }
                                            }()
                                        }
                                    var resp = regTbl[method](trans, m.params);
                                    trans.delayReturn() || trans.completed() || trans.complete(resp)
                                } catch (e) {
                                    var error = "runtime_error",
                                        message = null;
                                    if ("string" == typeof e ? message = e : "object" == typeof e && (e && s_isArray(e) && 2 == e.length ? (error = e[0], message = e[1]) : "string" == typeof e.error && (error = e.error, e.message ? "string" == typeof e.message ? message = e.message : e = e.message : message = "")), null === message) try {
                                        message = JSON.stringify(e), "undefined" == typeof message && (message = e.toString())
                                    } catch (e2) {
                                        message = e.toString()
                                    }
                                    trans.error(error, message)
                                }
                            }
                        } else m.id && m.callback ? outTbl[m.id] && outTbl[m.id].callbacks && outTbl[m.id].callbacks[m.callback] ? outTbl[m.id].callbacks[m.callback](m.params) : debug("ignoring invalid callback, id:" + m.id + " (" + m.callback + ")") : m.id ? outTbl[m.id] ? (m.error ? outTbl[m.id].error(m.error, m.message) : void 0 !== m.result ? outTbl[m.id].success(m.result) : outTbl[m.id].success(), delete outTbl[m.id], delete s_transIds[m.id]) : debug("ignoring invalid response: " + m.id) : method && regTbl[method] && regTbl[method]({
                            origin: origin
                        }, m.params)
                    };
                s_addBoundChan(cfg.window, cfg.origin, "string" == typeof cfg.scope ? cfg.scope : "", onMessage);
                var scopeMethod = function (m) {
                        return "string" == typeof cfg.scope && cfg.scope.length && (m = [cfg.scope, m].join("::")), m
                    },
                    postMessage = function (msg, force) {
                        if (!msg) throw "postMessage called with null message";
                        var verb = ready ? "post  " : "queue ";
                        if (debug(verb + " message: " + JSON.stringify(msg)), force || ready) {
                            if ("function" == typeof cfg.postMessageObserver) try {
                                cfg.postMessageObserver(cfg.origin, msg)
                            } catch (e) {
                                debug("postMessageObserver() raised an exception: " + e.toString())
                            }
                            cfg.window.postMessage(JSON.stringify(msg), cfg.origin)
                        } else pendingQueue.push(msg)
                    },
                    onReady = function (trans, type) {
                        if (debug("ready msg received"), ready) throw "received ready message while in ready state.  help!";
                        for (chanId += "ping" === type ? "-R" : "-L", obj.unbind("__ready"), ready = !0, debug("ready msg accepted."), "ping" === type && obj.notify({
                            method: "__ready",
                            params: "pong"
                        }); pendingQueue.length;) postMessage(pendingQueue.pop());
                        "function" == typeof cfg.onReady && cfg.onReady(obj)
                    },
                    obj = {
                        unbind: function (method) {
                            if (regTbl[method]) {
                                if (!delete regTbl[method]) throw "can't delete method: " + method;
                                return !0
                            }
                            return !1
                        },
                        bind: function (method, cb) {
                            if (!method || "string" != typeof method) throw "'method' argument to bind must be string";
                            if (!cb || "function" != typeof cb) throw "callback missing from bind params";
                            if (regTbl[method]) throw "method '" + method + "' is already bound!";
                            return regTbl[method] = cb, this
                        },
                        call: function (m) {
                            if (!m) throw "missing arguments to call function";
                            if (!m.method || "string" != typeof m.method) throw "'method' argument to call must be string";
                            if (!m.success || "function" != typeof m.success) throw "'success' callback missing from call";
                            var callbacks = {},
                                callbackNames = [],
                                seen = [],
                                pruneFunctions = function (path, obj) {
                                    if (seen.indexOf(obj) >= 0) throw "params cannot be a recursive data structure";
                                    if (seen.push(obj), "object" == typeof obj)
                                        for (var k in obj)
                                            if (obj.hasOwnProperty(k)) {
                                                var np = path + (path.length ? "/" : "") + k;
                                                "function" == typeof obj[k] ? (callbacks[np] = obj[k], callbackNames.push(np), delete obj[k]) : "object" == typeof obj[k] && null !== obj[k] && pruneFunctions(np, obj[k])
                                            }
                                };
                            pruneFunctions("", m.params);
                            var msg = {
                                id: s_curTranId,
                                method: scopeMethod(m.method),
                                params: m.params
                            };
                            callbackNames.length && (msg.callbacks = callbackNames), m.timeout && setTransactionTimeout(s_curTranId, m.timeout, scopeMethod(m.method)), outTbl[s_curTranId] = {
                                callbacks: callbacks,
                                error: m.error,
                                success: m.success
                            }, s_transIds[s_curTranId] = onMessage, s_curTranId++, postMessage(msg)
                        },
                        notify: function (m) {
                            if (!m) throw "missing arguments to notify function";
                            if (!m.method || "string" != typeof m.method) throw "'method' argument to notify must be string";
                            postMessage({
                                method: scopeMethod(m.method),
                                params: m.params
                            })
                        },
                        destroy: function () {
                            s_removeBoundChan(cfg.window, cfg.origin, "string" == typeof cfg.scope ? cfg.scope : ""), window.removeEventListener ? window.removeEventListener("message", onMessage, !1) : window.detachEvent && window.detachEvent("onmessage", onMessage), ready = !1, regTbl = {}, inTbl = {}, outTbl = {}, cfg.origin = null, pendingQueue = [], debug("channel destroyed"), chanId = ""
                        }
                    };
                return obj.bind("__ready", onReady), setTimeout(function () {
                    postMessage({
                        method: scopeMethod("__ready"),
                        params: "ping"
                    }, !0)
                }, 0), obj
            }
        }
    }(),
    AsyncStorage = function (jsChannel) {
        var emptyFn = function () {},
            getCallback = function (callback) {
                return "function" == typeof callback ? callback : emptyFn
            },
            setDefaults = function (defaults, options) {
                for (var key in defaults)!defaults.hasOwnProperty(key) || key in options || (options[key] = defaults[key])
            },
            StorageParent = function (options, iframe) {
                options = options || {};
                var self = this,
                    channel = null,
                    ready = !1,
                    readyQueue = [],
                    readyCallback = options.onReady,
                    defaults = {
                        origin: "*",
                        scope: "testScope"
                    };
                this._call = function (options) {
                    ready ? (options.success = getCallback(options.success), options.error = function (error, message) {
                        throw error + ": " + message
                    }, channel.call(options)) : readyQueue.push(options)
                }, setDefaults(defaults, options), options.onReady = function () {
                    ready = !0, "function" == typeof readyCallback && readyCallback();
                    for (var i = 0; i < readyQueue.length; i++) self._call(readyQueue[i])
                }, this.build = function (_iframe) {
                    options.window = _iframe.contentWindow, channel = jsChannel.build(options)
                }, iframe && this.build(iframe)
            },
            like = function (method, regex, modifiers, callback) {
                "function" == typeof modifiers && (callback = modifiers, modifiers = ""), this._call({
                    method: method,
                    params: {
                        regex: regex,
                        modifiers: modifiers
                    },
                    success: callback
                })
            };
        StorageParent.prototype = {
            length: function (callback) {
                this._call({
                    method: "length",
                    success: callback
                })
            },
            key: function (index, callback) {
                this._call({
                    method: "key",
                    params: index,
                    success: callback
                })
            },
            keysLike: function (regex, modifiers, callback) {
                like.call(this, "keysLike", regex, modifiers, callback)
            },
            getItem: function (key, callback) {
                this._call({
                    method: "getItem",
                    params: key,
                    success: callback
                })
            },
            getItems: function (keys, callback) {
                this._call({
                    method: "getItems",
                    params: keys,
                    success: callback
                })
            },
            getItemsWithKeysLike: function (regex, modifiers, callback) {
                like.call(this, "getItemsWithKeysLike", regex, modifiers, callback)
            },
            setItem: function (key, data, expires, callback) {
                "function" == typeof expires && (callback = expires, expires = null), this._call({
                    method: "setItem",
                    params: {
                        key: key,
                        data: data,
                        expires: expires
                    },
                    success: callback
                })
            },
            setItems: function (pairs, callback) {
                this._call({
                    method: "setItems",
                    params: pairs,
                    success: callback
                })
            },
            removeItem: function (key, callback) {
                this._call({
                    method: "removeItem",
                    params: key,
                    success: callback
                })
            },
            removeItems: function (keys, callback) {
                this._call({
                    method: "removeItems",
                    params: keys,
                    success: callback
                })
            },
            removeItemsWithKeysLike: function (regex, modifiers, callback) {
                like.call(this, "removeItemsWithKeysLike", regex, modifiers, callback)
            },
            clear: function (callback) {
                this._call({
                    method: "clear",
                    success: callback
                })
            }
        };
        var setupChild = function (window, options) {
            options = options || {};
            var defaults = {
                window: window.parent,
                origin: "*",
                scope: "testScope"
            };
            setDefaults(defaults, options);
            var channel = jsChannel.build(options),
                storage = options.storage || window.localStorage,
                keysLike = function (params) {
                    var r = new RegExp(params.regex, params.modifiers || ""),
                        keys = [];
                    for (var key in storage) r.test(key) && keys.push(key);
                    return keys
                },
                setItem = function (key, data, expires) {
                    return data = {
                        data: data
                    }, parseInt(expires) && (data.expires = (new Date).getTime() + expires), storage.setItem(key, JSON.stringify(data))
                },
                getItem = function (key) {
                    var item = storage.getItem(key);
                    if (item) {
                        try {
                            item = JSON.parse(item)
                        } catch (SyntaxError) {
                            return item
                        }
                        "object" == typeof item && "data" in item && (item.expires && item.expires < (new Date).getTime() && (storage.removeItem(key), item.data = null), item = item.data)
                    }
                    return item
                };
            for (var k in storage) getItem(k);
            channel.bind("length", function () {
                return storage.length
            }), channel.bind("key", function (trans, index) {
                return storage.key(index)
            }), channel.bind("keysLike", function (trans, params) {
                return keysLike(params)
            }), channel.bind("getItem", function (trans, key) {
                return getItem(key)
            }), channel.bind("getItems", function (trans, keys) {
                for (var items = {}, i = 0; i < keys.length; i++) items[keys[i]] = getItem(keys[i]);
                return items
            }), channel.bind("getItemsWithKeysLike", function (trans, params) {
                for (var keys = keysLike(params), items = {}, i = 0; i < keys.length; i++) items[keys[i]] = getItem(keys[i]);
                return items
            }), channel.bind("setItem", function (trans, params) {
                return setItem(params.key, params.data, params.expires)
            }), channel.bind("setItems", function (trans, pairs) {
                for (var key in pairs) pairs.hasOwnProperty(key) && setItem(key, pairs[key])
            }), channel.bind("removeItem", function (trans, key) {
                return storage.removeItem(key)
            }), channel.bind("removeItems", function (trans, keys) {
                for (var i = 0; i < keys.length; i++) storage.removeItem(keys[i])
            }), channel.bind("removeItemsWithKeysLike", function (trans, params) {
                for (var keys = keysLike(params), i = 0; i < keys.length; i++) storage.removeItem(keys[i])
            }), channel.bind("clear", function () {
                return storage.clear()
            })
        };
        return {
            parent: function (iframe, options) {
                return new StorageParent(iframe, options)
            },
            child: setupChild
        }
    }(Channel);
! function ($) {
    $.reject = function (options) {
        var opts = $.extend(!0, {
            reject: {
                all: !1,
                msie: 6
            },
            display: [],
            browserShow: !0,
            browserInfo: {
                firefox: {
                    text: "Mozilla Firefox",
                    url: "http://www.mozilla.com/firefox/"
                },
                chrome: {
                    text: "Google Chrome",
                    url: "http://www.google.com/chrome/"
                },
                safari: {
                    text: "Safari",
                    url: "http://www.apple.com/safari/download/"
                },
                opera: {
                    text: "Opera",
                    url: "http://www.opera.com/download/"
                },
                msie: {
                    text: "Internet Explorer",
                    url: "http://www.microsoft.com/windows/Internet-explorer/"
                }
            },
            header: "Did you know that your Internet Browser is out of date?",
            paragraph1: "Your browser is out of date, and may not be compatible with our website. A list of the most popular web browsers can be found below.",
            paragraph2: "Just click on the icons to get to the download page",
            close: !0,
            closeMessage: "By closing this window you acknowledge that your experience on this website may be degraded",
            closeLink: "Close This Window",
            closeURL: "#",
            closeESC: !0,
            closeCookie: !1,
            cookieSettings: {
                path: "/",
                expires: 0
            },
            imagePath: "./images/",
            overlayBgColor: "#000",
            overlayOpacity: .8,
            fadeInTime: "fast",
            fadeOutTime: "fast",
            analytics: !1
        }, options);
        opts.display.length < 1 && (opts.display = ["chrome", "firefox", "safari", "opera", "msie"]), $.isFunction(opts.beforeReject) && opts.beforeReject(), opts.close || (opts.closeESC = !1);
        var browserCheck = function (settings) {
            var layout = settings[$.layout.name],
                browser = settings[$.browser.name];
            return !!(settings.all || browser && (browser === !0 || $.browser.versionNumber <= browser) || settings[$.browser.className] || layout && (layout === !0 || $.layout.versionNumber <= layout) || settings[$.os.name])
        };
        if (!browserCheck(opts.reject)) return $.isFunction(opts.onFail) && opts.onFail(), !1;
        if (opts.close && opts.closeCookie) {
            var COOKIE_NAME = "jreject-close",
                _cookie = function (name, value) {
                    if ("undefined" != typeof value) {
                        var expires = "";
                        if (0 !== opts.cookieSettings.expires) {
                            var date = new Date;
                            date.setTime(date.getTime() + 1e3 * opts.cookieSettings.expires), expires = "; expires=" + date.toGMTString()
                        }
                        var path = opts.cookieSettings.path || "/";
                        return document.cookie = name + "=" + encodeURIComponent(value ? value : "") + expires + "; path=" + path, !0
                    }
                    var cookie, val = null;
                    if (document.cookie && "" !== document.cookie)
                        for (var cookies = document.cookie.split(";"), clen = cookies.length, i = 0; clen > i; ++i)
                            if (cookie = $.trim(cookies[i]), cookie.substring(0, name.length + 1) == name + "=") {
                                var len = name.length;
                                val = decodeURIComponent(cookie.substring(len + 1));
                                break
                            }
                    return val
                };
            if (_cookie(COOKIE_NAME)) return !1
        }
        var html = '<div id="jr_overlay"></div><div id="jr_wrap"><div id="jr_inner"><h1 id="jr_header">' + opts.header + "</h1>" + ("" === opts.paragraph1 ? "" : "<p>" + opts.paragraph1 + "</p>") + ("" === opts.paragraph2 ? "" : "<p>" + opts.paragraph2 + "</p>");
        if (opts.browserShow) {
            html += "<ul>";
            var displayNum = 0;
            for (var x in opts.display) {
                var browser = opts.display[x],
                    info = opts.browserInfo[browser] || !1;
                if (info && (void 0 == info.allow || browserCheck(info.allow))) {
                    var url = info.url || "#";
                    html += '<li id="jr_' + browser + '"><div class="jr_icon"></div><div><a href="' + url + '">' + (info.text || "Unknown") + "</a></div></li>", ++displayNum
                }
            }
            html += "</ul>"
        }
        html += '<div id="jr_close">' + (opts.close ? '<a href="' + opts.closeURL + '">' + opts.closeLink + "</a><p>" + opts.closeMessage + "</p>" : "") + "</div></div></div>";
        var element = $("<div>" + html + "</div>"),
            size = _pageSize(),
            scroll = _scrollSize();
        element.bind("closejr", function () {
            if (!opts.close) return !1;
            $.isFunction(opts.beforeClose) && opts.beforeClose(), $(this).unbind("closejr"), $("#jr_overlay,#jr_wrap").fadeOut(opts.fadeOutTime, function () {
                $(this).remove(), $.isFunction(opts.afterClose) && opts.afterClose()
            });
            var elmhide = "embed.jr_hidden, object.jr_hidden, select.jr_hidden, applet.jr_hidden";
            return $(elmhide).show().removeClass("jr_hidden"), opts.closeCookie && _cookie(COOKIE_NAME, "true"), !0
        });
        var analytics = function (url) {
                if (!opts.analytics) return !1;
                var host = url.split(/\/+/g)[1];
                try {
                    _gaq.push(["_trackEvent", "External Links", host, url])
                } catch (e) {
                    try {
                        pageTracker._trackEvent("External Links", host, url)
                    } catch (e) {}
                }
            },
            openBrowserLinks = function (url) {
                return analytics(url), window.open(url, "jr_" + Math.round(11 * Math.random())), !1
            };
        return element.find("#jr_overlay").css({
            width: size[0],
            height: size[1],
            background: opts.overlayBgColor,
            opacity: opts.overlayOpacity
        }), element.find("#jr_wrap").css({
            top: scroll[1] + size[3] / 4,
            left: scroll[0]
        }), element.find("#jr_inner").css({
            minWidth: 100 * displayNum,
            maxWidth: 140 * displayNum,
            width: "trident" == $.layout.name ? 155 * displayNum : "auto"
        }), element.find("#jr_inner li").css({
            background: 'transparent url("' + opts.imagePath + 'background_browser.gif")no-repeat scroll left top'
        }), element.find("#jr_inner li .jr_icon").each(function () {
            var self = $(this);
            self.css("background", "transparent url(" + opts.imagePath + "browser_" + self.parent("li").attr("id").replace(/jr_/, "") + ".gif) no-repeat scroll left top"), self.click(function () {
                var url = $(this).next("div").children("a").attr("href");
                openBrowserLinks(url)
            })
        }), element.find("#jr_inner li a").click(function () {
            return openBrowserLinks($(this).attr("href")), !1
        }), element.find("#jr_close a").click(function () {
            return $(this).trigger("closejr"), "#" === opts.closeURL ? !1 : void 0
        }), $("#jr_overlay").focus(), $("embed, object, select, applet").each(function () {
            $(this).is(":visible") && $(this).hide().addClass("jr_hidden")
        }), $("body").append(element.hide().fadeIn(opts.fadeInTime)), $(window).bind("resize scroll", function () {
            var size = _pageSize();
            $("#jr_overlay").css({
                width: size[0],
                height: size[1]
            });
            var scroll = _scrollSize();
            $("#jr_wrap").css({
                top: scroll[1] + size[3] / 4,
                left: scroll[0]
            })
        }), opts.closeESC && $(document).bind("keydown", function (event) {
            27 == event.keyCode && element.trigger("closejr")
        }), $.isFunction(opts.afterReject) && opts.afterReject(), !0
    };
    var _pageSize = function () {
            var xScroll = window.innerWidth && window.scrollMaxX ? window.innerWidth + window.scrollMaxX : document.body.scrollWidth > document.body.offsetWidth ? document.body.scrollWidth : document.body.offsetWidth,
                yScroll = window.innerHeight && window.scrollMaxY ? window.innerHeight + window.scrollMaxY : document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight,
                windowWidth = window.innerWidth ? window.innerWidth : document.documentElement && document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth,
                windowHeight = window.innerHeight ? window.innerHeight : document.documentElement && document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight;
            return [windowWidth > xScroll ? xScroll : windowWidth, windowHeight > yScroll ? windowHeight : yScroll, windowWidth, windowHeight]
        },
        _scrollSize = function () {
            return [window.pageXOffset ? window.pageXOffset : document.documentElement && document.documentElement.scrollTop ? document.documentElement.scrollLeft : document.body.scrollLeft, window.pageYOffset ? window.pageYOffset : document.documentElement && document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop]
        }
}(jQuery),
function ($) {
    $.browserTest = function (a, z) {
        var u = "unknown",
            x = "X",
            m = function (r, h) {
                for (var i = 0; i < h.length; i += 1) r = r.replace(h[i][0], h[i][1]);
                return r
            },
            c = function (i, a, b, c) {
                var r = {
                    name: m((a.exec(i) || [u, u])[1], b)
                };
                if (r[r.name] = !0, r.version = r.opera ? window.opera.version() : (c.exec(i) || [x, x, x, x])[3], /safari/.test(r.name)) {
                    var safariversion = /(safari)(\/|\s)([a-z0-9\.\+]*?)(\;|dev|rel|\s|$)/,
                        res = safariversion.exec(i);
                    res && res[3] && res[3] < 400 && (r.version = "2.0")
                } else "presto" === r.name && (r.version = $.browser.version > 9.27 ? "futhark" : "linear_b");
                r.versionNumber = parseFloat(r.version, 10) || 0;
                var minorStart = 1;
                return r.versionNumber < 100 && r.versionNumber > 9 && (minorStart = 2), r.versionX = r.version !== x ? r.version.substr(0, minorStart) : x, r.className = r.name + r.versionX, r
            };
        a = (/Opera|Navigator|Minefield|KHTML|Chrome|CriOS/.test(a) ? m(a, [
            [/(Firefox|MSIE|KHTML,\slike\sGecko|Konqueror)/, ""],
            ["Chrome Safari", "Chrome"],
            ["CriOS", "Chrome"],
            ["KHTML", "Konqueror"],
            ["Minefield", "Firefox"],
            ["Navigator", "Netscape"]
        ]) : a).toLowerCase(), $.browser = $.extend(z ? {} : $.browser, c(a, /(camino|chrome|crios|firefox|netscape|konqueror|lynx|msie|opera|safari)/, [], /(camino|chrome|crios|firefox|netscape|netscape6|opera|version|konqueror|lynx|msie|safari)(\/|\s)([a-z0-9\.\+]*?)(\;|dev|rel|\s|$)/)), $.layout = c(a, /(gecko|konqueror|msie|opera|webkit)/, [
            ["konqueror", "khtml"],
            ["msie", "trident"],
            ["opera", "presto"]
        ], /(applewebkit|rv|konqueror|msie)(\:|\/|\s)([a-z0-9\.]*?)(\;|\)|\s)/), $.os = {
            name: (/(win|mac|linux|sunos|solaris|iphone|ipad)/.exec(navigator.platform.toLowerCase()) || [u])[0].replace("sunos", "solaris")
        }, z || $("html").addClass([$.os.name, $.browser.name, $.browser.className, $.layout.name, $.layout.className].join(" "))
    }, $.browserTest(navigator.userAgent)
}(jQuery), Function.prototype.bind || (Function.prototype.bind = function (object) {
    var args = Array.prototype.slice.call(arguments, 2);
    return _.bind(this, object, args)
}), Function.prototype.extend = function (protoProps, staticProps) {
    var child, parent = this;
    child = protoProps && _.has(protoProps, "constructor") ? protoProps.constructor : function () {
        return parent.apply(this, arguments)
    }, _.extend(child, parent, staticProps);
    var Surrogate = function () {
        this.constructor = child
    };
    return Surrogate.prototype = parent.prototype, child.prototype = new Surrogate, protoProps && _.extend(child.prototype, protoProps), child.__super__ = parent.prototype, child
}, _.mixin(_.string.exports()), _.mixin({
    ucfirst: function (string) {
        return _.isString(string) ? string.charAt(0).toUpperCase() + string.substring(1).toLowerCase() : ""
    },
    isNumeric: function (n) {
        return !isNaN(parseFloat(n)) && isFinite(n)
    },
    nl2br: function (text) {
        return text.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, "$1<br />").replace(/(<br \/><br \/>)(?:<br \/>)+/g, "<br /><br />")
    },
    linkify: function (text, isEscaped) {
        isEscaped && (text = _.unescape(text));
        var matches = text.match(/\b((?:http(s)?:\/\/|(www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/))((?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?Â«Â»â€œâ€â€˜â€™])))/gi);
        return _.each(matches, function (url, index) {
            text = text.replace(url, "__url__" + index)
        }), isEscaped && (text = _.escape(text)), matches && _.each(matches, function (url, index) {
            var isInstaEDU = url.match(/^(?:http(?:s)?:[/]{2})?(?:\w*[.])?instaedu\.com/);
            text = text.replace("__url__" + index, _.sprintf('<a href="%s" %s>%s</a>', (url.match(/^http/) ? "" : "http://") + url, isInstaEDU ? "" : 'target="_blank" rel="nofollow"', _.escape(url)))
        }), text
    }
}), $.Event.prototype.wheel = function () {
    var delta = 0,
        event = this.originalEvent;
    return event.wheelDelta ? (delta = event.wheelDelta / 120, window.opera && (delta = -delta)) : event.detail && (delta = -event.detail / 3), delta
}, $.fn.extend({
    reverse: [].reverse,
    exists: function () {
        return this.length > 0
    },
    outerHTML: function (remove) {
        var $item = remove === !0 ? $(this) : $(this).clone();
        return $("<div/>").append($item).html()
    },
    pulsate: function (duration, pulses) {
        duration = duration || 200, pulses = pulses || 2;
        for (var i = 0; pulses > i; i++) this.fadeOut(duration).fadeIn(duration);
        return this
    },
    linkify: function (isEscaped) {
        return this.each(function () {
            var $this = $(this);
            $this.html(_.linkify($this.html(), isEscaped))
        })
    },
    nl2br: function () {
        return this.each(function () {
            var $this = $(this);
            $this.html(_.nl2br($this.html()))
        })
    },
    disable: function () {
        return this.prop("disabled", !0).addClass("disabled")
    },
    enable: function () {
        return this.prop("disabled", !1).removeClass("disabled")
    },
    disableAll: function () {
        return this.find(":input").prop("disabled", !0), this
    },
    enableAll: function () {
        return this.find(":input").prop("disabled", !1), this
    },
    isOnBottom: function () {
        return this.scrollTop() + this.height() >= this.prop("scrollHeight")
    },
    scrollToBottom: function () {
        return this.scrollTop(this.prop("scrollHeight")), this
    },
    scrollTo: function (target, options, callback) {
        "function" == typeof options && 2 == arguments.length && (callback = options, options = target);
        var settings = $.extend({
            scrollTarget: target,
            offsetTop: 50,
            duration: 500,
            easing: "swing"
        }, options);
        return this.each(function () {
            var scrollPane = $(this),
                scrollTarget = "number" == typeof settings.scrollTarget ? settings.scrollTarget : $(settings.scrollTarget),
                scrollY = "number" == typeof scrollTarget ? scrollTarget : scrollTarget.offset().top + scrollPane.scrollTop() - parseInt(settings.offsetTop);
            scrollPane.animate({
                scrollTop: scrollY
            }, parseInt(settings.duration), settings.easing, function () {
                "function" == typeof callback && callback.call(this)
            })
        })
    },
    serializeHash: function () {
        var o = {},
            a = this.serializeArray();
        return $.each(a, function () {
            void 0 !== o[this.name] ? (o[this.name].push || (o[this.name] = [o[this.name]]), o[this.name].push(this.value || "")) : o[this.name] = this.value || ""
        }), o
    },
    unserialize: function (values, callbacks) {
        if (!values) return this;
        callbacks = callbacks || {}, values = values.split("&");
        var serializedValues = [];
        return $.each(values, function () {
            var properties = this.split("=");
            if (!_.isUndefined(properties[0]) && !_.isUndefined(properties[1])) {
                var name = properties[0].replace(/\+/g, " "),
                    value = properties[1].replace(/\+/g, " ");
                name in serializedValues ? (_.isArray(serializedValues[name]) || (serializedValues[name] = [serializedValues[name]]), serializedValues[name].push(value)) : serializedValues[name] = value
            }
        }), values = serializedValues, this.find(":input:not(select)").prop("checked", !1).each(function () {
            var $this = $(this),
                tagName = $this.attr("name"),
                type = $this.attr("type");
            if (_.isUndefined(values[tagName])) "radio" == type && $this.prop("checked", !$this.val());
            else if (tagName in callbacks) callbacks[tagName]($this, values[tagName]);
            else switch (type) {
            case "checkbox":
                $this.prop("checked", !0);
                break;
            case "radio":
                $this.prop("checked", $this.val() == values[tagName]);
                break;
            default:
                $this.val(values[tagName])
            }
        }), this.find("select").each(function () {
            var $this = $(this),
                tagName = $this.attr("name");
            if (_.isUndefined(values[tagName]) ? values[tagName] = [] : _.isArray(values[tagName]) || (values[tagName] = [values[tagName]]), tagName in callbacks) callbacks[tagName]($this, values[tagName]);
            else {
                var changed = !1;
                $this.find("option").each(function () {
                    var $option = $(this),
                        existing = $option.prop("selected"),
                        selected = values[tagName].indexOf($option.val()) > -1;
                    existing != selected && ($option.prop("selected", selected), changed = !0)
                }), changed && ($this.change(), $this.trigger("liszt:updated"))
            }
        }), this
    },
    getSelectionStart: function () {
        var input = $(this)[0];
        if (input.createTextRange) {
            var range = document.selection.createRange().duplicate();
            return range.moveEnd("character", input.value.length), "" === range.text ? input.value.length : input.value.lastIndexOf(range.text)
        }
        return input.selectionStart
    },
    getSelectionEnd: function () {
        var input = $(this)[0];
        if (input.createTextRange) {
            var range = document.selection.createRange().duplicate();
            return range.moveStart("character", -input.value.length), range.text.length
        }
        return input.selectionEnd
    },
    selectRange: function (start, end) {
        return end || (end = start), this.each(function () {
            if (this.setSelectionRange) this.focus(), this.setSelectionRange(start, end);
            else if (this.createTextRange) {
                var range = this.createTextRange();
                range.collapse(!0), range.moveEnd("character", end), range.moveStart("character", start), range.select()
            }
        })
    }
}), $.extend({
    debug: function (message) {
        window.DEBUG && console.log(message)
    },
    escapeText: function (str) {
        return $("<div/>").text(str).html()
    }
}),
function ($) {
    "use strict";
    var Affix = function (element, options) {
        this.options = $.extend({}, $.fn.affix.defaults, options), this.$window = $(window).on("scroll.affix.data-api", $.proxy(this.checkPosition, this)).on("click.affix.data-api", $.proxy(function () {
            setTimeout($.proxy(this.checkPosition, this), 1)
        }, this)), this.$element = $(element), this.checkPosition()
    };
    Affix.prototype.checkPosition = function () {
        if (this.$element.is(":visible")) {
            var affix, scrollHeight = $(document).height(),
                scrollTop = this.$window.scrollTop(),
                windowHeight = this.$window.height(),
                position = this.$element.offset(),
                elHeight = this.$element.outerHeight(),
                offset = this.options.offset,
                offsetBottom = offset.bottom,
                offsetPadding = offset.padding || 0,
                offsetTop = offset.top,
                offsetHold = offset.hold,
                reset = "affix affix-top affix-bottom";
            if (!(elHeight > windowHeight))
                if (windowHeight + scrollTop > scrollHeight && (scrollTop = scrollHeight - windowHeight), "object" != typeof offset && (offsetBottom = offsetTop = offset), "function" == typeof offsetTop && (offsetTop = offset.top()), "function" == typeof offsetBottom && (offsetBottom = offset.bottom()), "function" == typeof offsetHold && (offsetHold = offset.hold()), offsetTop -= offsetPadding, offsetHold -= offsetPadding, affix = null !== this.unpin && scrollTop + this.unpin <= position.top ? !1 : null !== offsetHold && null !== this.hold && scrollTop >= offsetHold ? "top" : null !== offsetBottom && position.top + elHeight >= scrollHeight - offsetBottom ? "bottom" : null !== offsetTop && offsetTop >= scrollTop ? "top" : !1, this.hold = null !== offsetHold && "top" == affix && scrollTop >= offsetHold && offsetHold - offsetTop > 0, this.hold) this.$element.css("margin-top", offsetHold - scrollTop - offsetTop);
                else {
                    if (this.$element.css("margin-top", affix ? "" : "-" + offsetTop + "px"), this.affixed === affix) return;
                    this.affixed = affix, this.unpin = "bottom" == affix ? position.top - scrollTop : null, this.$element.removeClass(reset).addClass("affix" + (affix ? "-" + affix : ""))
                }
        }
    }, $.fn.affix = function (option) {
        return this.each(function () {
            var $this = $(this),
                data = $this.data("affix"),
                options = "object" == typeof option && option;
            data || $this.data("affix", data = new Affix(this, options)), "string" == typeof option && data[option]()
        })
    }, $.fn.affix.Constructor = Affix, $.fn.affix.defaults = {
        offset: 0
    }, $(window).on("load", function () {
        $('[data-spy="affix"]').each(function () {
            var $spy = $(this),
                data = $spy.data();
            data.offset = data.offset || {}, data.offsetBottom && (data.offset.bottom = data.offsetBottom), data.offsetTop && (data.offset.top = data.offsetTop), data.offsetHold && (data.offset.hold = data.offsetHold), $spy.affix(data)
        })
    })
}(window.jQuery), $("body").on("click", "a[bb-event]", function (event) {
    event.preventDefault();
    var bbEvent = $(this).attr("bb-event");
    Backbone.trigger(bbEvent, $(this), event)
}), _.extend(Backbone.Model.prototype, {
    autosave: function (hooks, timeToSave) {
        this.forceSave = this.save;
        var debounced = _.debounce(this.forceSave.bind(this), timeToSave || 500),
            save = function (attribs, options) {
                return options = options || {}, "function" == typeof attribs && (options.success = attribs, attribs = null), options.autosave ? void 0 : (options.autosave = !0, debounced(attribs, options))
            };
        this.save = save, this.triggerSave = function (obj, event) {
            obj.on(event, function () {
                save()
            })
        }, hooks = hooks || [], hooks.push([this, "change"]), _.each(hooks, function (hook) {
            this.triggerSave(hook[0], hook[1])
        }.bind(this))
    },
    eventPassthrough: function (collection, prefix) {
        collection.on("all", function () {
            var args = Array.prototype.slice.call(arguments, 1);
            args.unshift(prefix + arguments[0]), this.trigger.apply(this, args)
        }.bind(this))
    },
    updateID: function (id) {
        this.set(this.idAttribute, id), this.forceSave && this.forceSave()
    },
    removeAndAdd: function () {
        var collection = this.collection,
            options = {
                manual: !0
            };
        collection && (collection.remove(this, options), collection.add(this, options))
    }
}), _.extend(Backbone.Collection.prototype, {
    _like: function (options, model) {
        for (var key in options) {
            var val = model.get(key),
                checkVal = options[key].toLowerCase();
            if (val && _.isString(val) && _.str.include(val.toLowerCase(), checkVal)) return !0
        }
        return !1
    },
    like: function (options) {
        options = options || {};
        var matches = [];
        return _.each(this.models, function (model) {
            Backbone.Collection.prototype._like(options, model) && matches.push(model)
        }), matches
    },
    destroyMulti: function (comparator) {
        var toDelete = [];
        this.each(function (model) {
            comparator(model) && toDelete.push(model)
        }), _(toDelete).each(function (model) {
            model.destroy()
        })
    }
}), Backbone.View._extend = Backbone.View.extend, Backbone.View.extend = function (protoProps) {
    var view = Backbone.View._extend.apply(this, arguments);
    return protoProps && (view.prototype.events = _.extend({}, this.prototype.events, protoProps.events)), view
};
var overrideProps = function (view, protoProps) {
    protoProps && (view.prototype.ui = _.extend({}, this.prototype.ui, protoProps.ui), view.prototype.events = _.extend({}, this.prototype.events, protoProps.events), view.prototype.modelEvents = _.extend({}, this.prototype.modelEvents, protoProps.modelEvents), view.prototype.collectionEvents = _.extend({}, this.prototype.collectionEvents, protoProps.collectionEvents), view.prototype.templateHelpers = _.extend({}, this.prototype.templateHelpers, protoProps.templateHelpers))
};
Backbone.Marionette.View._extend = Backbone.Marionette.View.extend, Backbone.Marionette.ItemView._extend = Backbone.Marionette.ItemView.extend, Backbone.Marionette.View.extend = function (protoProps) {
    var view = Backbone.Marionette.View._extend.apply(this, arguments);
    return overrideProps.call(this, view, protoProps), view
}, Backbone.Marionette.ItemView.extend = function (protoProps) {
    var view = Backbone.Marionette.ItemView._extend.apply(this, arguments);
    return overrideProps.call(this, view, protoProps), view
}, Backbone.SearchHistory = Backbone.History.extend({
    trailingSlash: /\/$/,
    routeStripper: /^[#\/]|\s+$/g,
    pathStripper: /[#].*$/,
    getFragment: function (fragment, forcePushState) {
        if (!fragment)
            if (this._hasPushState || !this._wantsHashChange || forcePushState) {
                fragment = this.location.pathname + this.location.search;
                var root = this.root.replace(this.trailingSlash, "");
                fragment.indexOf(root) || (fragment = fragment.slice(root.length))
            } else fragment = this.getHash();
        return fragment.replace(this.routeStripper, "")
    },
    navigate: function (fragment, options) {
        if (!Backbone.History.started) return !1;
        options && options !== !0 || (options = {
            trigger: !!options
        });
        var url = this.root + (fragment = this.getFragment(fragment || ""));
        if (fragment = fragment.replace(this.pathStripper, ""), this.fragment !== fragment) {
            if (this.fragment = fragment, "" === fragment && "/" !== url && (url = url.slice(0, -1)), this._hasPushState) this.history[options.replace ? "replaceState" : "pushState"]({}, document.title, url);
            else {
                if (!this._wantsHashChange) return this.location.assign(url);
                this._updateHash(this.location, fragment, options.replace), this.iframe && fragment !== this.getFragment(this.getHash(this.iframe)) && (options.replace || this.iframe.document.open().close(), this._updateHash(this.iframe.location, fragment, options.replace))
            }
            return options.trigger ? this.loadUrl(fragment) : void 0
        }
    }
}), _.extend(Backbone.Marionette.CollectionView.prototype, {
    sortedAppend: function (collectionView, itemView, index, sortBefore) {
        var $items = collectionView.$el.children();
        0 === index ? collectionView.$el.prepend(itemView.$el) : $items.length > 0 && $items.eq(index).exists() ? $items.eq(index)[sortBefore ? "before" : "after"](itemView.$el) : collectionView.$el.append(itemView.$el)
    }
}), Backbone.NoSync = {
    Model: Backbone.Model.extend({
        sync: function () {
            return !0
        }
    }),
    Collection: Backbone.Collection.extend({
        sync: function () {
            return !0
        }
    })
}, Backbone.history = new Backbone.SearchHistory, _.extend(window.amplify.store, {
    update: function (key, data, expiration) {
        var orig = window.amplify.store(key);
        _.isObject(orig) && _.isObject(data) ? _.extend(orig, data) : orig = data, expiration = expiration ? expiration : 6048e5, window.amplify.store(key, orig, {
            expires: expiration
        })
    },
    findMatching: function (regex) {
        var matches = {};
        for (var key in window.localStorage) key.match(regex) && (matches[key] = key.match(/^__amplify__/) ? window.amplify.store(_.strRight(key, "__amplify__")) : window.localStorage.getItem(key));
        return matches
    },
    removeMatching: function (regex) {
        _.each(_.keys(window.amplify.store.findMatching(regex)), function (key) {
            window.localStorage.removeItem(key)
        })
    }
}), $.cookie.raw = !0, $.cookie.json = !0, $.cookie.defaults = {
    path: "/",
    secure: window.location.protocol.match(/^https/)
}, window.asyncStorage = window.AsyncStorage.parent({
    origin: "https://" + window.location.hostname + "/",
    scope: "ssl-storage"
}), define("config", function () {
    return window.muoicongConfig || {}
}), define("heartbeat", function () {
    return window.heartbeat
}), define("ack", function () {
    return window.ack
}), window.resourcesLoaded = !0, window.openChromelessPopup = function (popupURL) {
    return window.open(popupURL, "_blank", "toolbar=no, location=no, directories=no, status=yes, menubar=yes, scrollbars=yes, resizable=yes, copyhistory=yes, width=400, height=600"), !1
}, window.mixpanelTrack = function (event, params, cb) {
    return params || (params = {}), $.extend(params, {
        _isAuthenticated: window.isAuthenticated,
        pageName: window.pageName,
        _flowState: window.flowState,
        conversionStep: window.conversionStep
    }), window.useMixpanel ? cb ? window.MIXPANEL_IS_DOWN ? (cb(), void 0) : (window.mixpanel.track(event, params, cb), void 0) : (window.mixpanel.track(event, params), void 0) : (cb && cb(), void 0)
};
var showAccountDropdown = function () {
        document.getElementById("account-dropdown").style.display = "block"
    },
    getUrlVars = function () {
        var vars = {};
        return window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) {
            vars[key] = value
        }), vars
    },
    urldecode = function (str) {
        return decodeURIComponent((str + "").replace(/\+/g, "%20"))
    };
window.getNextURL = function () {
    var urlVars = getUrlVars();
    return "next" in urlVars ? document.location.protocol + "//" + document.location.host + urldecode(urlVars.next) : null
}, window.retry = function (args) {
    return "fn" in args || window.showErrorCatchall(), "counter" in args || (args.counter = 0), "maxRetries" in args || (args.maxRetries = 5), "retryIntervalMs" in args || (args.retryIntervalMs = 2500), args.counter++, args.counter == args.maxRetries ? ("errorCb" in args && args.errorCb(), void 0) : (setTimeout(function () {
        args.fn(args)
    }, args.retryIntervalMs), void 0)
}, window.delayedReload = function () {
    setTimeout(function () {
        location.reload(!0)
    }, 1e3)
}, $("#get-free-help-close").click(function () {
    return document.getElementById("get-free-help-overlay").style.display = "none", document.getElementById("cover").style.display = "none", !1
}), $("#account-dropdown-button").click(function () {
    return showAccountDropdown(), !1
});
var createLessonSuccess = function (data, lastLessonCode, isForwardedFrom) {
        if (!data.lessonCode) return window.showErrorCatchall(), void 0;
        var redirectURL = "/s/" + data.lessonCode + "/";
        isForwardedFrom && (redirectURL += "?ffs=" + lastLessonCode), document.location.href = redirectURL
    },
    createLessonTriggered = !1;
window.createLesson = function (options) {
    var opts = _.extend({
        searchQueryString: "",
        lastLessonCode: null,
        isForwardedFrom: null,
        lessonMedium: 3
    }, options);
    if (createLessonTriggered) return !1;
    createLessonTriggered = !0;
    var data = {
        csrfmiddlewaretoken: window.CSRF_TOKEN
    };
    opts.lastLessonCode ? data.lastLessonCode = opts.lastLessonCode : opts.searchQueryString && (data.searchQueryString = opts.searchQueryString);
    var $question = $("#student-question");
    $question.exists() && (data.question = $question.val()), data.lessonMedium = opts.lessonMedium;
    var ts = (new Date).getTime().toString();
    return $.ajax({
        url: "/create-session/?_=" + ts,
        type: "POST",
        dataType: "json",
        data: data,
        success: function (data) {
            createLessonSuccess(data, opts.lastLessonCode, opts.isForwardedFrom)
        },
        error: function () {
            window.showErrorCatchall()
        }
    }), !1
}, $("#autoshare-prompt-close").click(function () {
    return $.ajax({
        url: AUTOSHARE_HIDE_URL,
        type: "POST",
        dataType: "json",
        data: {
            csrfmiddlewaretoken: window.CSRF_TOKEN
        },
        success: function () {
            $("#autoshare-prompt").hide()
        },
        error: function () {
            $("#autoshare-prompt").hide()
        }
    }), !1
}), window.carouselStart = function (carouselDist, thumbDist) {
    var carousel = document.getElementById("carousel-list"),
        scrollbar = document.getElementById("carousel-scrollbar"),
        carouselLeft = 0,
        dif = -1,
        runSideScroller = !0,
        stopSideScroll = function () {
            return runSideScroller = !1, !1
        };
    $(".expert-img").each(function () {
        var $this = $(this);
        $this.css({
            "background-image": 'url("' + $this.data("url") + '")',
            "background-position": $this.data("position")
        })
    }), carousel.onmousedown = stopSideScroll, scrollbar.onmousedown = stopSideScroll;
    var sideScroll = function () {
        if (runSideScroller) {
            carouselLeft += dif, carousel.style.left = carouselLeft + "px";
            var scrollbarLeft = -carouselLeft * thumbDist / carouselDist;
            scrollbar.style.left = scrollbarLeft + "px", (0 === carouselLeft || carouselLeft == -carouselDist) && (dif = -dif), setTimeout(sideScroll, 50)
        }
    };
    sideScroll()
}, $("fieldset > h4").click(function () {
    var _this = $(this);
    return _this.toggleClass("expanded").parent().children("div").toggle(200), this.firstChild.innerHTML = "+" == this.firstChild.innerHTML ? "-" : "+", !1
});
var nots = ["form#subject-search-form label", "form#form-choose-subscription label", "form#profile-payment-form label", "#profile-schedule-form label", "form label.radio-btn-pair", "form .s-inputs label", "form#subjects_form label", "#chat-blast-message-form label"];
$("label").not(nots.join(",")).inFieldLabels().css("cursor", "text"), $("form#subject-search-form label").inFieldLabels({
    fadeOpacity: 1
}).css("cursor", "text"), $("label.pointer").css("cursor", "pointer"), $(".tooltip-target").tooltip(), $(".btn:not(.noreset)").button("reset");
var Retina = function () {
    return {
        init: function () {
            var pixelRatio = window.devicePixelRatio ? window.devicePixelRatio : 1,
                retinaImgs = ["img#new-logo"];
            pixelRatio > 1 && $(retinaImgs.join(",")).each(function (idx, el) {
                var $el = $(el);
                $el.attr("data-src2x") && ($el.attr("data-src-orig", $el.attr("src")), $el.attr("src", $el.attr("data-src2x")))
            })
        }
    }
}();
Retina.init(), window.loadEditProfile = function () {
    if ($("#id_password").on("focus", function () {
        $("#new-password-fields").fadeIn("fast")
    }), !window.isTutor) {
        $("#profile-submit").click(function () {
            $("#profile-form").submit()
        });
        var stripeResponseHandler = function (status, response) {
            if (response.error) $("#profile-payment-form button").toggleClass("disabled").removeAttr("disabled"), $(".payment-errors").html(response.error.message).show();
            else {
                var form$ = $("#profile-payment-form"),
                    token = response.id;
                form$.append('<input type="hidden" name="stripeToken" value="' + token + '">'), $.ajax({
                    url: window.CREATE_STRIPE_ACCOUNT_URL,
                    cache: !1,
                    type: "POST",
                    data: form$.serialize(),
                    success: function (data) {
                        data.oldID ? ($("#primary-card-number").hide().html("XXXX-XXXX-XXXX-<strong>" + data.lastFour + "</strong>").fadeIn("fast").effect("highlight"), $('<li class="credit-card-item">XXXX-XXXX-XXXX-' + data.oldLastFour + ' <span class="credit-card-actions"><a href="#" class="credit-card-label delete btn btn-xsmall"><span>' + data.oldID + '</span>Delete</a> <a href="#" class="credit-card-label make-primary btn btn-xsmall"><span>' + data.oldID + "</span>Make primary</a></span></li>").hide().appendTo("#credit-cards ul").fadeIn("fast"), $("a.delete").on("click", deleteStripeAccount)) : $("#primary-card-container").html('<div id="primary-card" class="left"><strong>Primary card:</strong> <span id="primary-card-number">XXXX-XXXX-XXXX-<strong>' + data.lastFour + '</strong></span><br><span id="primary-card-explanation">Only your primary card will be used.</span></div>').hide().fadeIn("fast"), $("#profile-payment-form button").toggleClass("disabled").removeAttr("disabled"), form$[0].reset(), $("#id_card_number").focus(), $(".payment-errors").hide(), $("a.delete").on("click", deleteStripeAccount)
                    },
                    error: function () {
                        window.showErrorCatchall()
                    }
                })
            }
        };
        $("#profile-payment-form").submit(function () {
            return $("#profile-payment-form button").toggleClass("disabled").prop("disabled", !0), window.Stripe.setPublishableKey(window.STRIPE_PUBLISHABLE_KEY), window.Stripe.createToken({
                number: $(".card_number").val(),
                cvc: $(".card_cvv").val(),
                exp_month: $(".expiration_date_month").val(),
                exp_year: $(".expiration_date_year").val()
            }, stripeResponseHandler), !1
        });
        var deleteStripeAccount = function (event) {
                var _this = $(event.target);
                _this.off("click"), $.ajax({
                    url: window.DELETE_STRIPE_ACCOUNT_URL,
                    cache: !1,
                    type: "POST",
                    data: {
                        csrfmiddlewaretoken: window.CSRF_TOKEN,
                        stripeProfileID: _this.find("span").text()
                    },
                    success: function () {
                        _this.parent().parent().fadeOut("fast")
                    },
                    error: function () {
                        window.showErrorCatchall()
                    }
                })
            },
            makeStripeAccountPrimary = function (event) {
                var _this = $(event.target);
                $.ajax({
                    url: window.MAKE_STRIPE_ACCOUNT_PRIMARY_URL,
                    cache: !1,
                    type: "POST",
                    data: {
                        csrfmiddlewaretoken: window.CSRF_TOKEN,
                        stripeProfileID: _this.find("span").text()
                    },
                    success: function (data) {
                        $("#primary-card-number").hide().html("XXXX-XXXX-XXXX-<strong>" + data.newPrimaryLastFour + "</strong>").fadeIn("fast").effect("highlight"), _this.parent().parent().hide(), $('<li class="credit-card-item">XXXX-XXXX-XXXX-' + data.oldPrimaryLastFour + ' <span class="credit-card-actions"><a href="#" class="credit-card-label delete btn btn-xsmall"><span>' + data.oldPrimaryID + '</span>Delete</a> <a href="#" class="credit-card-label make-primary btn btn-xsmall"><span>' + data.oldPrimaryID + "</span>Make primary</a></span></li>").hide().appendTo("#credit-cards ul").fadeIn("fast"), $("a.delete").on("click", deleteStripeAccount)
                    },
                    error: function () {
                        window.showErrorCatchall()
                    }
                })
            };
        return $("a.delete").on("click", deleteStripeAccount), $("#credit-cards").on("click", "a.make-primary", makeStripeAccountPrimary), void 0
    }
    var jcropAPI = !1,
        cropBtnActive = !0,
        imageEditInProgress = !1,
        resetCoords = function (startingWidth) {
            $("#x").val(0), $("#y").val(0), $("#w").val(startingWidth), $("#h").val(startingWidth)
        },
        updateCoords = function (c) {
            $("#x").val(c.x), $("#y").val(c.y), $("#w").val(c.w), $("#h").val(c.h)
        },
        jcropRelease = function () {
            resetCoords(0)
        },
        jcropInit = function (dimX, dimY, dimW, dimH, thumbnailSize) {
            $("#profile-image").removeAttr("style").Jcrop({
                minSize: [thumbnailSize, thumbnailSize],
                onSelect: updateCoords,
                onRelease: jcropRelease,
                setSelect: [dimX, dimY, dimW, dimH],
                aspectRatio: 1
            }, function () {
                updateCoords({
                    x: dimX,
                    y: dimY,
                    w: dimW,
                    h: dimH
                }), jcropAPI = this
            })
        },
        userImageLoad = function (dimX, dimY, dimW, dimH, startingWidth, thumbnailSize) {
            resetCoords(startingWidth), jcropInit(dimX, dimY, dimW, dimH, thumbnailSize)
        },
        uploadErrorCb = function () {
            $("#popup-content").html($("#image-error").html()), $("#update-image").val(0), window.showLightbox()
        };
    $("#profile-form").ajaxForm(), $("#id_image_full").change(function () {
        imageEditInProgress || (imageEditInProgress = !0, jcropAPI && jcropAPI.destroy(), resetCoords(0), $("#update-image").val(1), $("#profile-form").ajaxSubmit({
            dataType: "json",
            cache: !1,
            success: function (data) {
                $("#update-image").val(0), $("#profile-image").removeClass("image300"), data.imageClass.length && $("#profile-image").addClass(data.imageClass), $("#profile-image").unbind("load"), $("#profile-image").load(function () {
                    userImageLoad(data.dimX, data.dimY, data.dimW, data.dimH, data.startingWidth, data.thumbnailSize), imageEditInProgress = !1
                }), $("#profile-image").attr("src", data.imageURL), window.hasPhoto = !0, window.hasCroppedPhoto = !1
            },
            error: uploadErrorCb
        }))
    }), $("#crop-photo").click(function () {
        return !cropBtnActive || imageEditInProgress ? !1 : ($("#crop-photo").button("loading"), imageEditInProgress = !0, jcropAPI && jcropAPI.destroy(), $("#crop-image").val(1), $("#profile-form").ajaxSubmit({
            dataType: "json",
            cache: !1,
            success: function (data) {
                $("#crop-photo").button("reset"), $("#crop-image").val(0), $("#profile-image").removeClass("image300"), data.imageClass.length && $("#profile-image").addClass(data.imageClass), $("#profile-image").unbind("load"), $("#profile-image").load(function () {
                    userImageLoad(data.dimX, data.dimY, data.dimW, data.dimH, data.startingWidth, data.thumbnailSize), imageEditInProgress = !1
                }), $("#profile-image").attr("src", data.imageURL), window.hasCroppedPhoto = !0
            },
            error: function () {
                $("#crop-photo").button("reset"), $("#crop-image").val(0), window.showErrorCatchall()
            }
        }), !1)
    }), $("#profile-submit").click(function () {
        return window.hasPhoto ? window.hasCroppedPhoto ? ($("#update-image").val(0), $("#crop-image").val(0), require(["profiles/edit"], function (edit) {
            (!window.isTutor || edit.validateTestScores()) && $("#profile-form").unbind("submit").submit()
        }), !1) : ($("#popup-content").html($("#image-crop-error").html()), window.showLightbox(), !1) : ($("#popup-content").html($("#no-image-error").html()), window.showLightbox(), !1)
    }), userImageLoad(document.getElementById("x").value, document.getElementById("y").value, document.getElementById("w").value, document.getElementById("h").value, window.startingWidth, window.thumbnailSize)
}, define("page-signup-add-student", function () {
    return {
        init: function () {
            $("form.onboarding-modal").on("submit", function () {
                $(this).find("button").button("loading")
            })
        }
    }
}), define("page-interview", ["profiles/edit"], function (edit) {
    edit.initInterview({
        $form: $("#interview-form")
    })
}), window.loadPresessionPaywall = function (options) {
    var opts = _.extend({
        searchQueryString: ""
    }, options);
    $(".start-search").click(function () {
        return window.createLesson({
            searchQueryString: opts.searchQueryString,
            lastLessonCode: null,
            isForwardedFrom: !1
        }), !1
    })
}, define("page-question", ["chat/constants", "questions/views", "experts/views", "questions/models", "util"], function (constants, views, experts, models, util) {
    var cancelModal, moreInfoModal, CancelQuestion = Backbone.View.extend({
            events: {
                "click .cancel": "cancelQuestion"
            },
            cancelQuestion: function (event) {
                var model = new models.Question;
                util.API.formSubmit(this.$el, event, {
                    callback: model.cancel.bind(model),
                    $btn: $(event.target),
                    redirects: !0,
                    ajaxOptions: {
                        csrf: !0,
                        success: function (data) {
                            location.href = data.redirectURL
                        },
                        error: function (data, xhr) {
                            403 == xhr.status && (this.$el.modal("hide"), $("#cancel-claimed-modal").modal("show"))
                        }.bind(this)
                    }
                })
            }
        }),
        MoreInfoModal = views.MoreInfoModal.extend({
            submitQuestion: function (event) {
                this.dismiss();
                var data = this.getData();
                if (this.validate(data)) {
                    var $form = this.$("form");
                    util.API.formSubmit($form, event, {
                        endpoint: models.Question.ENDPOINTS.resubmit,
                        data: data,
                        redirects: !0,
                        ajaxOptions: {
                            csrf: !0,
                            success: function () {
                                window.location.href = window.location.href
                            }
                        }
                    })
                }
            },
            getData: function () {
                var data = views.MoreInfoModal.prototype.getData.call(this),
                    formData = this.$("form").serializeHash();
                return _.extend(data, {
                    text: formData.text,
                    recipient: formData.recipient,
                    subject_keyword: formData.subject_keyword
                })
            }
        });
    return Backbone.on("question.cancel", function () {
        cancelModal || (cancelModal = new CancelQuestion({
            el: $("#cancel-question-modal")
        })), cancelModal.$el.modal("show")
    }), $(".how-does-this-work").on("click", function () {
        $("#how-does-this-work-modal").modal("show")
    }), {
        init: function (opts) {
            var $filterForm = $(".filter-form");
            $(".subject-message-form").each(function () {
                new experts.MessageForm({
                    el: $(this),
                    $filterForm: $filterForm
                })
            }), Backbone.on("question.resubmit", function ($el) {
                moreInfoModal || (moreInfoModal = new MoreInfoModal({
                    el: $("#more-info-modal"),
                    tutorSubjectsURL: opts.tutorSubjectsURL,
                    userID: opts.userID
                })), moreInfoModal.show($el.attr("data-subject"), moreInfoModal.getSelectedTutor()), $("#id_subject_keyword").chosen()
            });
            var $showMore = $("#show-more"),
                $questionContainer = $("#question-container"),
                $questionContainerText = $("#question-container .text");
            $questionContainerText.height() > $questionContainer.height() ? $showMore.on("click", function () {
                $questionContainer.css({
                    "max-height": "none",
                    overflow: "auto"
                }), $showMore.hide()
            }) : $showMore.hide(), $(".expert-message").on("click", function (event) {
                experts.openChatBox(event, "question")
            }), $(".meet-now-link").on("click", function (event) {
                experts.startMeetNow(event, "question-page")
            })
        }
    }
}), window.loadStripeHandler = function () {
    var showError = function (error) {
            $("#profile-payment-form button").toggleClass("disabled").removeAttr("disabled"), $(".payment-errors").html(error).show()
        },
        stripeResponseHandler = function (status, response) {
            if (response.error) return showError(response.error.message), void 0;
            var form$ = $("#profile-payment-form"),
                token = response.id;
            form$.append('<input type="hidden" name="stripeToken" value="' + token + '">'), $.ajax({
                url: window.CREATE_STRIPE_ACCOUNT_URL,
                cache: !1,
                type: "POST",
                data: form$.serialize(),
                success: function (data) {
                    data.oldID ? ($("#primary-card-number").hide().html("XXXX-XXXX-XXXX-<strong>" + data.lastFour + "</strong>").fadeIn("fast").effect("highlight"), $('<li class="credit-card-item">XXXX-XXXX-XXXX-' + data.oldLastFour + ' <span class="credit-card-actions"><a href="#" class="credit-card-label delete btn btn-xsmall"><span>' + data.oldID + '</span>Delete</a> <a href="#" class="credit-card-label make-primary btn btn-xsmall"><span>' + data.oldID + "</span>Make primary</a></span></li>").hide().appendTo("#credit-cards ul").fadeIn("fast"), $("a.delete").on("click", deleteStripeAccount)) : $("#primary-card-container").html('<div id="primary-card" class="left"><strong>Primary card:</strong> <span id="primary-card-number">XXXX-XXXX-XXXX-<strong>' + data.lastFour + '</strong></span><br><span id="primary-card-explanation">Only your primary card will be used.</span></div>').hide().fadeIn("fast"), $("#profile-payment-form button").toggleClass("disabled").removeAttr("disabled"), form$[0].reset(), $("#id_card_number").focus(), $(".payment-errors").hide(), $("#add-credit-card-form").slideUp("fast"), $("#add-card-link").fadeIn(), $("a.delete").on("click", deleteStripeAccount)
                },
                error: function (xhr) {
                    var data = {};
                    try {
                        data = $.parseJSON(xhr.responseText)
                    } catch (e) {}
                    return data.error ? (showError(data.error), void 0) : (window.showErrorCatchall(), void 0)
                }
            })
        };
    $("#profile-payment-form").submit(function () {
        return $("#profile-payment-form button").toggleClass("disabled").prop("disabled", !0), window.Stripe.setPublishableKey(window.STRIPE_PUBLISHABLE_KEY), window.Stripe.createToken({
            number: $(".card_number").val(),
            cvc: $(".card_cvv").val(),
            exp_month: $(".expiration_date_month").val(),
            exp_year: $(".expiration_date_year").val()
        }, stripeResponseHandler), !1
    });
    var deleteStripeAccount = function (event) {
            var _this = $(event.target);
            _this.off("click"), $.ajax({
                url: window.DELETE_STRIPE_ACCOUNT_URL,
                cache: !1,
                type: "POST",
                data: {
                    csrfmiddlewaretoken: window.CSRF_TOKEN,
                    stripeProfileID: _this.find("span").text()
                },
                success: function () {
                    _this.parent().parent().fadeOut("fast")
                },
                error: function () {
                    window.showErrorCatchall()
                }
            })
        },
        makeStripeAccountPrimary = function (event) {
            var _this = $(event.target);
            $.ajax({
                url: window.MAKE_STRIPE_ACCOUNT_PRIMARY_URL,
                cache: !1,
                type: "POST",
                data: {
                    csrfmiddlewaretoken: window.CSRF_TOKEN,
                    stripeProfileID: _this.find("span").text()
                },
                success: function (data) {
                    $("#primary-card-number").hide().html("XXXX-XXXX-XXXX-<strong>" + data.newPrimaryLastFour + "</strong>").fadeIn("fast").effect("highlight"), _this.parent().parent().hide(), $('<li class="credit-card-item">XXXX-XXXX-XXXX-' + data.oldPrimaryLastFour + ' <span class="credit-card-actions"><a href="#" class="credit-card-label delete btn btn-xsmall"><span>' + data.oldPrimaryID + '</span>Delete</a> <a href="#" class="credit-card-label make-primary btn btn-xsmall"><span>' + data.oldPrimaryID + "</span>Make primary</a></span></li>").hide().appendTo("#credit-cards ul").fadeIn("fast"), $("a.delete").on("click", deleteStripeAccount)
                },
                error: function () {
                    window.showErrorCatchall()
                }
            })
        };
    $("a.delete").on("click", deleteStripeAccount), $("#credit-cards").on("click", "a.make-primary", makeStripeAccountPrimary), $(".expiration_date_month").val(_.sprintf("%02d", (new Date).getMonth() + 1))
}, define("page-choose-trial", ["payment-info", "chat/constants"], function (paymentInfo, constants) {
    return {
        init: function (showPaywallMessage) {
            paymentInfo.loadPaymentInfo(), new paymentInfo.changeCommitmentForm({
                el: $("#form-choose-subscription")
            }), showPaywallMessage && setTimeout(function () {
                Backbone.trigger("chat:su-message", constants.MESSAGE_CONTEXT.SU_PAYWALL, "on-page")
            }, 12e4)
        }
    }
}), define("page-inbox-conversation", ["inbox/views", "schedule/views", "chat/models/users", "chat/phrasebank", "base/models", "base/constants", "util", "config", "socket"], function (inbox, schedule, users, phrasebank, baseModels, constants, util, config, socket) {
    var inboxView, RespondView = inbox.NewMessageView.extend({
            events: {
                "click .open-phrasebank": "togglePhrasebank"
            },
            getUploadURL: function () {
                return _.sprintf(config.BASE_URL + "inbox/attachment/%s/", config.CONVERSATION_ID)
            },
            success: function (data) {
                inboxView.addMessage(data.html), this.$form[0].reset()
            },
            togglePhrasebank: function (event) {
                phrasebank(this, this.$(".open-phrasebank"), this.otherUniqueID, function (phraseText) {
                    this.$textarea.val(phraseText)
                }.bind(this), event.type)
            }
        }),
        init = function (opts) {
            var userID = opts.userID,
                alertElem = opts.alertElem,
                parentID = opts.parentID;
            inboxView = inbox.setupInbox({
                moreToLoad: opts.moreToLoad,
                startID: opts.startID,
                view: inbox.ConversationView,
                loadMoreURL: opts.loadMoreURL,
                forwardsState: opts.forwardsState,
                backwardsState: opts.backwardsState
            });
            var alertView = new inbox.NewMessageAlertView({
                    el: alertElem,
                    inbox: inboxView
                }),
                timezoneOffsetMinutes = opts.timezoneOffsetMinutes,
                timezoneOffsetStr = util.getTimezoneOffset(timezoneOffsetMinutes);
            $(".conversation-timezone-icon").attr("data-title", timezoneOffsetStr).tooltip();
            var connections = baseModels.Manager.getCollection("connections");
            connections.done(function () {
                var connection = connections.findWhere({
                    id: opts.forwardsConnection
                });
                $(".unblock-user").on("click", function () {
                    return connection.set("state", constants.CONNECTION_STATE.NORMAL), connection.save().done(function () {
                        window.location.reload(!0)
                    }), !1
                })
            }.bind(this)), new schedule.ProposeNewLesson({
                el: $("#conversation")
            }), new RespondView({
                el: $("#form-wrapper"),
                otherUniqueID: opts.otherUniqueID
            }), socket.subscribe("user=" + userID, {
                "inbox:new.message": function (data) {
                    var attrs = _.extend(data, {
                        parentID: parentID
                    });
                    inboxView.renderMessage(attrs, function (showAlert) {
                        showAlert && alertView.incrementCount().render().show()
                    })
                }
            }), $("#message-cta .js-request-question").on("click", function () {
                users.Cache.getUserInfo(opts.otherUniqueID).done(function (user) {
                    Backbone.trigger("chat:request.question", user)
                })
            })
        };
    return {
        init: init
    }
}), define("page-campaign", ["util", "profiles/views", "experts/views", "subjects/search", "config"], function (util, profiles, experts, search, config) {
    $('select[name$="subject"]').chosen();
    var view = new search.SubjectSearchView({
        el: $("#subject-search-form")
    });
    config.isAuthenticated || view.ui.subject.focus(), $(".recent-subject").on("click", function (event) {
        var $link = $(event.target);
        return view.setSubject($link.text()), view.ui.label.hide(), $link.button("loading"), view.submitSubject(), !1
    });
    var SignupForm = Backbone.View.extend({
        events: {
            "click .btn-primary": "submitForm"
        },
        submitForm: function (event) {
            var data = this.$el.serializeHash();
            data.subject = this.$("#id_subject").val(), util.API.formSubmit(this.$el, event, {
                data: data,
                endpoint: document.URL,
                redirects: !0,
                ajaxOptions: {
                    success: function (data) {
                        if (data.content) {
                            this.el.reset();
                            var $content = $(data.content);
                            $("body").append($content);
                            var form = new profiles.NewPasswordForm({
                                el: $content,
                                ajaxOptions: {
                                    success: function () {
                                        location.href = data.nextURL
                                    }.bind(this)
                                }
                            });
                            return form.show(), void 0
                        }
                        return data.nextURL ? (location.href = data.nextURL, void 0) : (this.$(".btn-primary").hide(), this.$("textarea").replaceWith($("<p/>").html("Your message has been sent!")), void 0)
                    }.bind(this)
                }
            })
        }
    });
    return function (selector) {
        new SignupForm({
            el: selector
        }), $(".expert-message").on("click", function (event) {
            experts.openChatBox(event, "campaign")
        })
    }
}),
function (w, d, s) {
    function loadFacebookSDK() {
        var js, fjs = d.getElementsByTagName(s)[0],
            load = function (url, id) {
                d.getElementById(id) || (js = d.createElement(s), js.src = url, js.id = id, fjs.parentNode.insertBefore(js, fjs))
            };
        load("//connect.facebook.net/en_US/all.js")
    }
    w.addEventListener ? w.addEventListener("load", loadFacebookSDK, !1) : w.attachEvent && w.attachEvent("onload", loadFacebookSDK)
}(window, document, "script"), window.fbAsyncInit = function () {
    window.FB.init({
        appId: window.FACEBOOK_APP_ID,
        channelUrl: "//" + window.location.hostname + "/fb_channel.html",
        status: !0,
        cookie: !0,
        xfbml: !0
    });
    var headerSubject = null,
        facebookSignUpSuccess = function (data, obj, redirectURL) {
            if (redirectURL) return window.location.href = redirectURL, void 0; {
                if (!data.name || !data.email) {
                    var nextURL = window.getNextURL();
                    return nextURL ? (window.location.href = nextURL, void 0) : data.nextURL ? (window.location.href = data.nextURL, void 0) : (window.location.reload(), void 0)
                }
                var $signupPagebox, $fbformPagebox, destPosX, offsetPosX, isSignUpPage = $(obj).attr("data-isSignUpPage");
                if (isSignUpPage) $signupPagebox = $("#page-signup-container"), $fbformPagebox = $("#page-facebook-final-step"), destPosX = $fbformPagebox.css("margin-left"), destPosX = parseInt(destPosX.slice(0, -2)), offsetPosX = destPosX - 350, $fbformPagebox.find("#page-fb-id-signup-name").val(data.name), $fbformPagebox.find("#page-fb-id-signup-email").val(data.email), $fbformPagebox.find("#page-id-signup-fb_user_id").val(data.facebookUserID), $signupPagebox.animate({
                    marginLeft: "200px",
                    opacity: "0"
                }, 500, "linear", function () {
                    $(this).css("display", "none"), $fbformPagebox.css({
                        "margin-left": offsetPosX + "px",
                        visibility: "visible"
                    }).animate({
                        marginLeft: destPosX + "px"
                    }, 500, "easeOutCubic")
                });
                else {
                    $signupPagebox = $("#signup-container"), $fbformPagebox = $("#facebook-final-step");
                    var $modalBackdrop = $("body > div.modal-backdrop");
                    destPosX = $fbformPagebox.css("margin-left"), destPosX = parseInt(destPosX.slice(0, -2)), offsetPosX = destPosX - 350, $fbformPagebox.find("#fb-id-signup-name").val(data.name), $fbformPagebox.find("#fb-id-signup-email").val(data.email), $fbformPagebox.find("#id-signup-fb_user_id").val(data.facebookUserID), $signupPagebox.animate({
                        left: "200px",
                        opacity: "0"
                    }, 500, "linear", function () {
                        $(this).css("display", "none"), $fbformPagebox.css({
                            "margin-left": offsetPosX + "px",
                            visibility: "visible"
                        }).animate({
                            marginLeft: destPosX + "px"
                        }, 500, "easeOutCubic")
                    }), $modalBackdrop.on("click", function (e) {
                        $fbformPagebox.animate({
                            opacity: "0"
                        }, 300, "linear", function () {
                            $(this).css({
                                visibility: "hidden",
                                opacity: 1
                            }), $(".signup-webform-modal").modal("hide"), $signupPagebox.css({
                                left: destPosX,
                                opacity: 1
                            }), e.stopPropagation()
                        })
                    })
                }
            }
        },
        facebookSignupError = function (xhr) {
            var data = {};
            try {
                data = $.parseJSON(xhr.responseText)
            } catch (e) {}
            if (401 == xhr.status) {
                if (data.noFacebookEmail) return window.showErrorCatchall(), void 0;
                if (data.noFacebookName) return window.showErrorCatchall(), void 0;
                if (data.signInError) {
                    var $elem = $(this).parent();
                    return $elem.find(".sign-in-form-error:visible") ? $elem.find(".sign-in-form-error").fadeOut("100", function () {
                        $elem.find(".facebook-sign-in-error").slideDown("200").fadeIn()
                    }) : $elem.find(".sign-in-form-error").slideDown("200").fadeIn(), window.hasOwnProperty("shiftSignInPrompt") && window.shiftSignInPrompt(), void 0
                }
                return window.showErrorCatchall(), void 0
            }
            return 403 == xhr.status ? (window.showErrorCatchall(), void 0) : (window.showErrorCatchall(), void 0)
        },
        facebookSignUp = function (obj, scope, signUpURL, redirectURL) {
            window.FB.login(function (response) {
                response.authResponse && $.ajax({
                    url: signUpURL,
                    type: "POST",
                    dataType: "json",
                    cache: !1,
                    data: {
                        csrfmiddlewaretoken: window.CSRF_TOKEN,
                        access_token: response.authResponse.accessToken,
                        path: document.location.pathname,
                        subject: headerSubject
                    },
                    success: function (data) {
                        facebookSignUpSuccess(data, obj, redirectURL)
                    },
                    error: facebookSignupError.bind(obj)
                })
            }, {
                scope: scope
            })
        },
        facebookShare = function (shareContext) {
            var url = null,
                name = null,
                caption = null,
                description = null;
            switch (shareContext) {
            case window.SHARE_CONTEXT.Q_AND_A:
                url = "http://instaedu.com/qr/" + window.REFERRAL_CODE + "/", name = "Check out InstaEDU for homework help", caption = "You can ask any question about homework and receive a free written explanation in a few hours.", description = "";
                break;
            case window.SHARE_CONTEXT.EXPLANATION:
                url = "http://instaedu.com/e/" + window.explanationCode + "/", name = "I just helped someone with " + window.subjectKeyword + " on InstaEDU.", caption = "", description = window.questionText;
                break;
            default:
                url = "http://instaedu.com/r/" + window.REFERRAL_CODE + "/", name = "Get instant homework help on InstaEDU", caption = "Connect with a subject expert the moment you have a question.", description = "Sign up with this link and try InstaEDU for free."
            }
            var obj = {
                method: "feed",
                link: url,
                name: name,
                caption: caption,
                description: description,
                display: "popup"
            };
            window.FB.ui(obj, function () {})
        },
        facebookMessage = function () {
            window.FB.ui({
                method: "send",
                link: $("#referral-code").val(),
                picture: "http://instaedu.com/publish/static/img/EDU-icon.png",
                display: "popup"
            }, function (response) {
                response && response.success && $("#success-container").show()
            })
        };
    $(".facebook-gift-share").click(function () {
        return facebookMessage(), !1
    }), $(".facebook-share").click(function () {
        return facebookShare(window.SHARE_CONTEXT.LESSON), !1
    }), $(".facebook-questions-share").click(function () {
        return facebookShare(window.SHARE_CONTEXT.Q_AND_A), !1
    }), $(".facebook-explanation-share").click(function () {
        return facebookShare(window.SHARE_CONTEXT.EXPLANATION), !1
    }), $(".login-with-facebook.signup").click(function () {
        return facebookSignUp(this, window.FACEBOOK_STUDENT_SCOPE, window.FACEBOOK_CONNECT_SIGN_UP_URL), !1
    }), $(".login-with-facebook.signin").click(function () {
        return facebookSignUp(this, window.FACEBOOK_STUDENT_SCOPE, window.FACEBOOK_CONNECT_SIGN_IN_URL), !1
    }), $(".facebook-header.signin").on("click", function () {
        return headerSubject = $("#id_header-subject").val(), facebookSignUp(this, window.FACEBOOK_STUDENT_SCOPE, window.FACEBOOK_CONNECT_SIGN_IN_URL), !1
    }), "/become-a-tutor/" == document.location.pathname && ($("#facebook-sign-up-expert").unbind("click").click(function () {
        return facebookSignUp(this, window.FACEBOOK_TUTOR_SCOPE, window.FACEBOOK_CONNECT_TUTOR_SIGN_UP_URL), !1
    }), $("#facebook-sign-up-expert-disabled").tooltip()), $("#facebook-autoshare").click(function () {
        return facebookSignUp(this, window.FACEBOOK_TUTOR_SCOPE + ",publish_actions", window.FACEBOOK_AUTOSHARE_SUCCESS_URL), !1
    }), window.facebookOgShareExplanation = function (explanationURL) {
        window.FB.api("/me/" + window.FACEBOOK_NAMESPACE + ":help_with", "post", {
            question: window.BASE_URL + explanationURL.substring(1)
        }, function (response) {
            return !response || response.error ? (window.ratchetConsoleLog("Error posting student explanation to FB Open Graph", response), setTimeout(function () {
                location.href = explanationURL
            }, 1e3), void 0) : (location.href = explanationURL, void 0)
        })
    }
}, define("page-index-expert", ["experts/availability", "schedule/views", "util"], function (avail, schedule, util) {
    schedule.setupIndexPage(), new avail.Toggles({
        el: "#tutor-availability-toggles"
    }), $("#tutor-progress li span").hasClass("complete") ? $("#tutor-progress li").removeClass("clickable") : $("#tutor-progress li.clickable").on("click", function (e) {
        e.preventDefault(), window.location.href = $(this).attr("data-url")
    }), $("#dismiss-training").on("click", function () {
        $("#complete-training").fadeOut("fast"), $("#tutor-homepage .approval-cta").fadeOut("fast"), $("#tutor-training-status").fadeOut("fast"), util.API.post("/orientation/", {
            csrf: !0,
            data: {
                step: "HIDDEN"
            }
        })
    });
    var $backgroundCheckApplyButton = $("#tutor-background-check-btn");
    $backgroundCheckApplyButton.exists() && $backgroundCheckApplyButton.on("click", function () {
        util.API.post("expert/background-check/", {
            csrf: !0,
            data: {
                interested: 1
            },
            success: function () {
                window.location.reload()
            },
            error: function () {
                window.showErrorCatchall()
            }
        })
    });
    var newModal, ModalView = Backbone.View.extend({
            events: {
                "click .btn-primary": "interested",
                "click .no-thanks": "notInterested"
            },
            initialize: function (options) {
                this.endpoint = options.endpoint
            },
            show: function () {
                this.$el.modal("show")
            },
            hide: function () {
                this.$el.modal("hide")
            },
            interested: function () {
                this.recordStatus(!0), this.displayModal(!0)
            },
            notInterested: function () {
                this.recordStatus(!1), this.displayModal(!1)
            },
            onRecordSuccess: function () {},
            onRecordError: function () {},
            recordStatus: function (interested) {
                util.API.post(this.endpoint, {
                    csrf: !0,
                    data: {
                        interested: interested ? 1 : 0
                    },
                    success: this.onRecordSuccess.bind(this),
                    error: this.onRecordError.bind(this)
                })
            },
            displayModal: function (interested) {
                if (interested) {
                    this.$(".modal-prompt").hide(), this.$(".modal-success").show();
                    var self = this;
                    setTimeout(function () {
                        self.$el.fadeOut(function () {
                            self.hide()
                        })
                    }, 3e3)
                } else this.hide()
            }
        }),
        $backgroundCheckModal = $("#background-check-modal"),
        $ambassadorModal = $("#campus-ambassador-modal");
    if ($backgroundCheckModal.exists()) {
        var Modal = ModalView.extend({
            displayModal: function (interested) {
                if (interested) this.hide(), window.open("https://ca.fadv.com/CA/welcome.do?instaeduFADV/SCRegister", "_blank");
                else {
                    this.$(".modal-prompt").hide(), this.$(".modal-decline").show();
                    var self = this;
                    setTimeout(function () {
                        self.$el.fadeOut(function () {
                            self.hide()
                        })
                    }, 3e3), $(".modal-backdrop").one("click", function () {
                        self.hide()
                    })
                }
            },
            onRecordSuccess: function () {
                window.location.reload()
            },
            onRecordError: function () {
                window.showErrorCatchall()
            }
        });
        newModal = new Modal({
            el: $backgroundCheckModal,
            endpoint: "expert/background-check/"
        }), newModal.show()
    } else $ambassadorModal.exists() && (newModal = new ModalView({
        el: $ambassadorModal,
        endpoint: "expert/campus-ambassador/"
    }), newModal.show())
}), define("page-index-parent", ["schedule/views"], function (schedule) {
    $(function () {
        schedule.setupIndexPage()
    })
}), define("payment-info", ["config", "track-conversion", "util"], function (config, trackConversion, util) {
    var loadPaymentInfo = function () {
            var redirectToNextUrl = function (data) {
                    data && data.redirectURL && !config.meetNowExpireTime ? window.location.href = data.redirectURL : config.meetNowExpireTime || (window.location.href = "/")
                },
                createStripeAccountSuccess = function (data) {
                    window.mixpanelTrack("Submitted Form", {
                        name: "payment-form"
                    }, function () {
                        trackConversion.track(config.revAmt, function () {
                            if (data.agreementPrice) {
                                var valueInCents = 100 * data.agreementPrice;
                                window.optimizely = window.optimizely || [], window.optimizely.push(["trackEvent", "conversion", {
                                    revenue: valueInCents
                                }])
                            }
                            redirectToNextUrl(data)
                        })
                    })
                },
                stripeResponseHandler = function (status, response) {
                    if (response.error) return $("#form-choose-subscription button").removeAttr("disabled").button("reset"), $("#form-choose-subscription .payment-errors").html(response.error.message).show(), void 0;
                    var $form = $("#form-choose-subscription"),
                        token = response.id;
                    $form.append('<input type="hidden" name="stripeToken" value="' + token + '">');
                    var ts = (new Date).getTime().toString();
                    util.API.post(window.CREATE_STRIPE_ACCOUNT_URL + "?_=" + ts, {
                        data: $form.serialize(),
                        success: createStripeAccountSuccess,
                        error: function (data) {
                            return data.error ? ($("#form-choose-subscription button").removeAttr("disabled").button("reset"), $(".payment-errors").html(data.error).show(), void 0) : (window.showErrorCatchall(), void 0)
                        }
                    })
                };
            new window.FormValidator("form-choose-subscription", [{
                name: "agreement-type",
                display: "Subscription Plan",
                rules: "required"
            }, {
                name: "id_card_number",
                display: "Credit Card Number",
                rules: "required"
            }, {
                name: "id_expiration_date_month",
                display: "Month",
                rules: "required"
            }, {
                name: "id_expiration_date_year",
                display: "Year",
                rules: "required"
            }, {
                name: "id_cvv",
                display: "CVV",
                rules: "required"
            }], function (errors, event) {
                if (errors.length > 0) {
                    for (var errorString = "", onFocus = function (e) {
                        $(e.currentTarget).removeClass("error")
                    }, i = 0, errorLength = errors.length; errorLength > i; i++) $("#" + errors[i].id).addClass("error").focus(onFocus), errorString += errors[i].message + "<br />";
                    return $("#form-choose-subscription").find(".form-errors").html(errorString).slideDown(150), !1
                }
                stripeInit(event)
            });
            var stripeInit = function (event) {
                var $form = $("#form-choose-subscription");
                $form.find("button").prop("disabled", !0).button("loading"), $form.find(".form-errors").hide(), window.Stripe.setPublishableKey(config.STRIPE_PUBLISHABLE_KEY), window.Stripe.createToken({
                    number: $form.find("#id_card_number").val(),
                    cvc: $form.find("#id_cvv").val(),
                    exp_month: $form.find("#id_expiration_date_month").val(),
                    exp_year: $form.find("#id_expiration_date_year").val()
                }, stripeResponseHandler), event.preventDefault()
            }
        },
        ChangeCommitmentForm = Backbone.View.extend({
            events: {
                "click .free-trial-choice": "chooseFreeTrial",
                "click li.item-plan": "planClickHandler",
                "click .questions-trial": "questionClickHandler"
            },
            chooseSubscription: function ($itemPlan) {
                $("ul#plan-options li.item-plan").each(function (index, elem) {
                    $(elem).removeClass("active")
                });
                var current = $itemPlan.find("input.plan-radio");
                current.prop("checked", !0), $itemPlan.addClass("active"), $("#sub-summary .minutes-per-week").html($itemPlan.attr("data-discount-time")), $("#sub-summary .plan-minutes-recap").html($itemPlan.attr("data-cost")), $("#sub-summary header h3").html($itemPlan.attr("data-plan-name"))
            },
            planClickHandler: function (event) {
                var $target = $(event.currentTarget);
                this.chooseSubscription($target)
            },
            questionClickHandler: function (event) {
                var $target = $(event.currentTarget);
                this.chooseSubscription($target)
            },
            chooseFreeTrial: function (event) {
                $("input[name=agreement-type]").each(function (index, elem) {
                    $(elem).parent().parent().removeClass("selected")
                });
                var $target = $(event.target).closest(".free-trial-choice"),
                    current = $target.find(".radio-button > input");
                current.prop("checked", !0);
                var currentParent = current.parent().parent();
                currentParent.addClass("selected"), $(".discount-time-string").html(currentParent.attr("data-discount-time")), $(".setup-fee-string").html(currentParent.attr("data-setup-fee")), $(".setup-fee-dollars-string").html(currentParent.attr("data-setup-fee-dollars")), $(".discount-time-label").html(currentParent.attr("data-discount-label")), $(".bill-at-start-adj").html(currentParent.attr("data-bill-at-start-adj")), this.chooseSubscription($target)
            },
            initialize: function () {
                this.chooseSubscription($(".item-plan.active")), $("#id_expiration_date_month").val(_.sprintf("%02d", (new Date).getMonth() + 1))
            }
        });
    return {
        changeCommitmentForm: ChangeCommitmentForm,
        loadPaymentInfo: loadPaymentInfo
    }
}), define("page-scheduling", ["schedule/views"], function (views) {
    views.setupLessonsPage()
}), define("notifications", ["socket", "notifications/views"], function (socket, views) {
    var init = function (userID) {
        var proposals = new views.NotificationView({
            el: $("#notifications .scheduled-lessons .new")
        });
        socket.subscribe("user=" + userID, {
            "schedule:new.proposal": _.bind(proposals.incrementCount, proposals),
            "schedule:read.proposal": _.bind(proposals.decrementCount, proposals)
        })
    };
    return {
        init: init
    }
}), define("browser", function () {
    var BrowserDetect = {
        init: function () {
            this.browser = this.searchString(this.dataBrowser) || "An unknown browser", this.version = this.searchVersion(navigator.userAgent) || this.searchVersion(navigator.appVersion) || "an unknown version", this.OS = this.searchString(this.dataOS) || "an unknown OS"
        },
        searchString: function (data) {
            for (var i = 0; i < data.length; i++) {
                var dataString = data[i].string,
                    dataProp = data[i].prop;
                if (this.versionSearchString = data[i].versionSearch || data[i].identity, dataString) {
                    if (-1 != dataString.indexOf(data[i].subString)) return data[i].identity
                } else if (dataProp) return data[i].identity
            }
        },
        searchVersion: function (dataString) {
            var index = dataString.indexOf(this.versionSearchString);
            if (-1 != index) return parseFloat(dataString.substring(index + this.versionSearchString.length + 1))
        },
        dataBrowser: [{
            string: navigator.userAgent,
            subString: "Chrome",
            identity: "Chrome"
        }, {
            string: navigator.userAgent,
            subString: "OmniWeb",
            versionSearch: "OmniWeb/",
            identity: "OmniWeb"
        }, {
            string: navigator.vendor,
            subString: "Apple",
            identity: "Safari",
            versionSearch: "Version"
        }, {
            prop: window.opera,
            identity: "Opera",
            versionSearch: "Version"
        }, {
            string: navigator.vendor,
            subString: "iCab",
            identity: "iCab"
        }, {
            string: navigator.vendor,
            subString: "KDE",
            identity: "Konqueror"
        }, {
            string: navigator.userAgent,
            subString: "Firefox",
            identity: "Firefox"
        }, {
            string: navigator.vendor,
            subString: "Camino",
            identity: "Camino"
        }, {
            string: navigator.userAgent,
            subString: "Netscape",
            identity: "Netscape"
        }, {
            string: navigator.userAgent,
            subString: "MSIE",
            identity: "Explorer",
            versionSearch: "MSIE"
        }, {
            string: navigator.userAgent,
            subString: "Gecko",
            identity: "Mozilla",
            versionSearch: "rv"
        }, {
            string: navigator.userAgent,
            subString: "Mozilla",
            identity: "Netscape",
            versionSearch: "Mozilla"
        }],
        dataOS: [{
            string: navigator.platform,
            subString: "Win",
            identity: "Windows"
        }, {
            string: navigator.platform,
            subString: "Mac",
            identity: "Mac"
        }, {
            string: navigator.userAgent,
            subString: "iPhone",
            identity: "iPhone/iPod"
        }, {
            string: navigator.platform,
            subString: "Linux",
            identity: "Linux"
        }]
    };
    return BrowserDetect.init(), {
        getBrowser: function () {
            return BrowserDetect.browser.toLowerCase()
        },
        isChrome: function () {
            return "Chrome" == BrowserDetect.browser
        },
        isFirefox: function () {
            return "Firefox" == BrowserDetect.browser
        },
        isIE: function () {
            return "Explorer" == BrowserDetect.browser
        },
        isSafari: function () {
            return "Safari" == BrowserDetect.browser
        },
        isMac: function () {
            return "Mac" == BrowserDetect.OS
        }
    }
}), window.loadEditProfile = function () {
    var jcropAPI = !1,
        cropBtnActive = !0,
        imageEditInProgress = !1,
        setProPicModalVisibility = function (vis) {
            vis ? ($("#propic-modal").removeClass("hide-propic-modal").addClass("show-propic-modal"), $("#blocking").fadeIn()) : ($("#propic-modal").addClass("hide-propic-modal").removeClass("show-propic-modal"), $("#blocking").fadeOut())
        },
        resetCoords = function (startingWidth) {
            $("#x").val(0), $("#y").val(0), $("#w").val(startingWidth), $("#h").val(startingWidth)
        },
        updateCoords = function (c) {
            $("#x").val(c.x), $("#y").val(c.y), $("#w").val(c.w), $("#h").val(c.h)
        },
        jcropRelease = function () {
            resetCoords(0)
        },
        jcropInit = function (dimX, dimY, dimW, dimH, thumbnailSize) {
            $("#profile-image").removeAttr("style").Jcrop({
                minSize: [thumbnailSize, thumbnailSize],
                onSelect: updateCoords,
                onRelease: jcropRelease,
                setSelect: [dimX, dimY, dimW, dimH],
                aspectRatio: 1
            }, function () {
                updateCoords({
                    x: dimX,
                    y: dimY,
                    w: dimW,
                    h: dimH
                }), jcropAPI = this
            })
        },
        userImageLoad = function (dimX, dimY, dimW, dimH, startingWidth, thumbnailSize) {
            resetCoords(startingWidth), jcropInit(dimX, dimY, dimW, dimH, thumbnailSize)
        },
        uploadErrorCb = function () {
            $("#update-image").val(0), $("#popup-content").html($("#image-error").html()), window.showLightbox()
        };
    $("#profile-form").ajaxForm(), $("#id_image_full").change(function () {
        imageEditInProgress || (imageEditInProgress = !0, jcropAPI && jcropAPI.destroy(), resetCoords(0), $("#update-image").val(1), $("#profile-form").ajaxSubmit({
            dataType: "json",
            cache: !1,
            success: function (data) {
                $("#update-image").val(0), $("#profile-image").removeClass("image300"), data.imageClass.length && $("#profile-image").addClass(data.imageClass), $("#profile-image").unbind("load"), $("#profile-image").load(function () {
                    userImageLoad(data.dimX, data.dimY, data.dimW, data.dimH, data.startingWidth, data.thumbnailSize), imageEditInProgress = !1
                }), $("#profile-image").attr("src", data.imageURL), window.hasPhoto = !0, window.hasCroppedPhoto = !1
            },
            error: uploadErrorCb
        }))
    }), $("#crop-photo").click(function () {
        return !cropBtnActive || imageEditInProgress ? !1 : ($("#crop-photo").button("loading"), imageEditInProgress = !0, jcropAPI && jcropAPI.destroy(), $("#crop-image").val(1), $("#profile-form").ajaxSubmit({
            dataType: "json",
            cache: !1,
            success: function (data) {
                $("#crop-photo").button("reset"), $("#crop-image").val(0), setProPicModalVisibility(!1), $(".expert.profile.full-profile .photo").attr("src", data.imageURL), $("#profile-image").attr("src", data.imageURL), $("#profile-image").removeClass("image300"), data.imageClass.length && $("#profile-image").addClass(data.imageClass), $("#profile-image").unbind("load"), $("#profile-image").load(function () {
                    userImageLoad(data.dimX, data.dimY, data.dimW, data.dimH, data.startingWidth, data.thumbnailSize), imageEditInProgress = !1
                }), window.hasCroppedPhoto = !0
            },
            error: function () {
                $("#crop-photo").button("reset"), $("#crop-image").val(0), setProPicModalVisibility(!1), window.showErrorCatchall()
            }
        }), !1)
    }), $("#profile-submit").click(function () {
        return window.hasPhoto ? window.hasCroppedPhoto ? ($("#update-image").val(0), $("#crop-image").val(0), require(["profiles/edit"], function (edit) {
            (!window.isTutor || edit.validateTestScores()) && $("#profile-form").unbind("submit").submit()
        }), !1) : ($("#popup-content").html($("#image-crop-error").html()), window.showLightbox(), !1) : ($("#popup-content").html($("#no-image-error").html()), window.showLightbox(), !1)
    }), userImageLoad(document.getElementById("x").value, document.getElementById("y").value, document.getElementById("w").value, document.getElementById("h").value, window.startingWidth, window.thumbnailSize), $("#blocking").click(function () {
        setProPicModalVisibility(!1)
    }), $(".photo.edit-photo").click(function () {
        setProPicModalVisibility(!0)
    })
}, window.loadIndex = function () {
    function testimonialPage(page) {
        $("#scroller").css("left", -961 * (page - 1)), $(".dot").addClass("doto").removeClass("dotc"), $("#dot" + page).addClass("dotc")
    }
    $("#on-demand-try-it-free").click(function () {
        var top = $("#try-it-now").offset().top;
        return $("html, body").animate({
            scrollTop: top + "px"
        }, 400), !1
    }), $("#find-an-online-tutor").click(function () {
        var top = $("#try-live-tutoring").offset().top;
        return $("html, body").animate({
            scrollTop: top + "px"
        }, 400), !1
    }), window.hasCarousel && setTimeout(function () {
        var options = {
            axis: "x",
            size: 940,
            scroll: !1
        };
        window.muoicongConfig.isMobile && (options.scrollInvert = !0), $("#carousel-scroll-container").tinyscrollbar(options), window.carouselStart(1608, 588.6)
    }, 1500), require(["subjects/search", "config"], function (search, config) {
        var view = new search.SubjectSearchView({
            el: $("#subject-search-form")
        });
        config.isAuthenticated || view.ui.subject.focus(), $(".recent-subject").click(function (event) {
            var $link = $(event.target);
            return view.setSubject($link.text()), view.ui.label.hide(), $link.button("loading"), view.submitSubject(), !1
        })
    }), $(".doto").click(function () {
        testimonialPage($(this).attr("id").charAt(3))
    }), testimonialPage(1)
}, define("page-index-student", ["schedule/views", "questions/models", "questions/views"], function (schedule, qModels, qViews) {
    var init = function (opts) {
        opts = opts || {}, schedule.setupIndexPage(), qModels.setEndpoints({
            "ask-and-signup": "question/ask/"
        }), new qViews.AskQuestionView({
            el: "#question-form",
            tutorSubjectsURL: opts.tutorSubjectsURL,
            userID: opts.userID
        })
    };
    return {
        init: init
    }
}), define("page-public-profile", ["experts/views", "schedule/meet-now", "schedule/views", "base/models", "base/constants", "chat/models/users", "config", "events", "util"], function (views, meetNow, scheduling, baseModels, constants, users, config, events, util) {
    var ReviewsContainer = Backbone.Marionette.View.extend({
        events: {
            "click .pagination-container a": "fetchPage"
        },
        fetchPage: function (e) {
            e.preventDefault(), util.API.post($(e.target).attr("href"), {
                csrf: !0,
                data: {
                    dataType: "reviews"
                },
                success: function (data) {
                    this.$el.html(data.html)
                }.bind(this)
            })
        }
    });
    return $(".mask.mobile-only").on("click", function () {
        return $(this).parents(".tab-pane").toggleClass("expanded"), !1
    }), {
        init: function (endpoints, options) {
            var $messageForm = $(".message-form"),
                $meetNowContainer = $("#public-profile-meet-now"),
                $meetNowButton = $meetNowContainer.find(".cta-red");
            options.forwardsState == constants.CONNECTION_STATE.BLOCKED ? ($("#public-profile-sidebar-blocked").show(), $("#unblock-user").on("click", function () {
                var connections = baseModels.Manager.getCollection("connections");
                connections.done(function () {
                    var connection = connections.findWhere({
                        user: options.userID,
                        otherUser: options.otherUserID
                    });
                    return connection.set("state", constants.CONNECTION_STATE.NORMAL), connection.save(), $("#public-profile-sidebar-blocked").hide(), $("#public-profile-sidebar").show(), $messageForm.show(), $meetNowContainer.addClass("show-meet-now-button"), !1
                }.bind(this))
            }), $meetNowContainer.hide()) : options.backwardsState == constants.CONNECTION_STATE.BLOCKED ? ($messageForm.hide(), $meetNowContainer.removeClass("show-meet-now-button")) : ($messageForm.show(), $meetNowContainer.addClass("show-meet-now-button"));
            var messageForm = new views.MessageForm({
                    el: $messageForm,
                    ENDPOINTS: endpoints
                }),
                schedulingForm = new scheduling.SchedulingSidebar({
                    el: $(".schedule-with-tutor-form"),
                    deferChosen: !0
                });
            new views.ProfileSidebar({
                messageForm: messageForm,
                schedulingForm: schedulingForm
            }), $meetNowButton.on("click", function () {
                var user = users.Cache.getUser(config.tutorID);
                meetNow.start(user.id, user.get("name"), "tutor-profile", config.subjectID)
            }), meetNow.setupPage($meetNowContainer), $("#public-profile-written-lesson-button").on("click", function () {
                events.create(events.EVENT.WRITTEN_LESSON_FOR_TUTOR_REQUEST, {
                    context: "public-profile"
                })
            })
        },
        ReviewsContainer: ReviewsContainer
    }
}), define("socket", ["config", "rollbar", "util"], function (config, rollbar, util) {
    var socket, io = window.io,
        loaded = window.socketLoaded,
        sockets = {},
        empty = function () {},
        socketMethods = ["emit", "on", "disconnect", "removeListener"],
        mixin = {
            emitToRoom: function (room, event, data) {
                this.socket.emit("emitToRoom", {
                    room: room,
                    event: event,
                    data: data
                })
            },
            emitToOthers: function (room, event, data) {
                this.socket.emit("emitToOthers", {
                    room: room,
                    event: event,
                    data: data
                })
            },
            subscribe: function (room, events) {
                this.rooms[room] || (this.rooms[room] = [], this.socket.emit("subscribeTo", room), this.socket.on("reconnect", function () {
                    this.socket.emit("subscribeTo", room)
                }.bind(this))), _.each(events, function (callback, event) {
                    this.rooms[room].push(event), this.eventList[event] || (this.eventList[event] = []), _.contains(this.eventList[event], callback) || (this.eventList[event].push(callback), this.socket.on(event, callback))
                }.bind(this))
            },
            unsubscribe: function (room, events) {
                _.contains(this.rooms, room) && (events || (events = this.rooms[room], this.socket.emit("unsubscribeFrom", room)), _.each(events, function (event) {
                    this.socket.removeListener(event)
                }.bind(this)))
            },
            enableRollbarLogging: function () {
                var self = this,
                    defaultHandlers = {
                        connect: rollbar.log,
                        reconnect: rollbar.log,
                        disconnect: rollbar.warn,
                        connect_failed: rollbar.error,
                        error: rollbar.error
                    };
                _.each(defaultHandlers, function (logger, event) {
                    self.socket.on(event, function (error) {
                        var title = event + (self.namespace ? "[" + self.namespace + "]" : "");
                        error = error ? ": " + error : "", logger("socket.io " + title + error)
                    })
                })
            }
        },
        IEDUSocket = function (namespace) {
            var self = this;
            util.makeDeferred(this), _.each(socketMethods.concat(_.keys(mixin)), function (method) {
                self[method] = empty
            }), loaded && this.resolve(), this.namespace = namespace || "", sockets[this.namespace] = this, this.rooms = {}, this.eventList = {}
        };
    return socket = new IEDUSocket, loaded && _.each(sockets, function (socket) {
        socket.resolve()
    }), {
        socket: socket,
        emit: socket.emit.bind(socket),
        on: socket.on.bind(socket),
        disconnect: socket.disconnect.bind(socket),
        subscribe: socket.subscribe.bind(socket),
        unsubscribe: socket.unsubscribe.bind(socket),
        emitToRoom: socket.emitToRoom.bind(socket),
        emitToOthers: socket.emitToOthers.bind(socket),
        loaded: loaded,
        connect: function (namespace) {
            return namespace = namespace || "", namespace in sockets || (sockets[namespace] = new IEDUSocket(namespace)), sockets[namespace]
        },
        init: function () {
            loaded = window.initSocket(), io = window.io
        }
    }
}), window.loadLogin = function () {
    if (window.isAuthenticated) {
        var nextURL = window.getNextURL();
        return nextURL ? (window.location.href = nextURL, void 0) : (window.location.href = window.BASE_URL, void 0)
    }
}, define("track-conversion", [], function () {
    var loadAdwords = function () {
            var scriptDef = new $.Deferred;
            $.getScript("//www.googleadservices.com/pagead/conversion.js", function () {
                scriptDef.resolve()
            });
            var imgDef = new $.Deferred,
                img = new Image(1, 1);
            img.src = "//www.googleadservices.com/pagead/conversion/1015601303/?value=0&label=gnuvCIm0tAcQl7Gj5AM&guid=ON&script=0", img.onload = function () {
                imgDef.resolve()
            };
            var def = new $.Deferred;
            return $.when(imgDef, scriptDef).then(function () {
                def.resolve()
            }), def
        },
        loadFacebook = function () {
            var fb_param = {};
            fb_param.pixel_id = "6009704416012", fb_param.value = "0.00", fb_param.currency = "USD";
            var def = new $.Deferred;
            return function () {
                var fpw = document.createElement("script");
                fpw.async = !0, fpw.src = "//connect.facebook.net/en_US/fp.js", fpw.onload = function () {
                    def.resolve()
                };
                var ref = document.getElementsByTagName("script")[0];
                ref.parentNode.insertBefore(fpw, ref)
            }(), def
        },
        loadMixpanel = function () {
            var def = new $.Deferred;
            return window.mixpanel.track("Credit Card Conversion", {}, function () {
                def.resolve()
            }), def
        },
        loadBing = function () {
            var def = new $.Deferred;
            window.mstag || (window.mstag = {
                loadTag: function () {},
                time: (new Date).getTime()
            });
            var s = document.createElement("script");
            return s.id = "mstag_tops", s.type = "text/javascript", s.onload = function () {
                window.mstag.loadTag("analytics", {
                    dedup: "1",
                    domainId: "2229273",
                    type: "1",
                    revenue: "",
                    actionid: "156949"
                }), def.resolve()
            }, s.src = "//flex.msn.com/mstag/site/0c68c71d-838b-4a7a-9366-5a0896e5330e/mstag.js", document.body.appendChild(s), def
        },
        loadPerfectAudience = function () {
            var def = new $.Deferred;
            return window._pa.track("First Credit Card"), def.resolve(), def
        },
        loadHasOffers = function (revAmt) {
            var def = new $.Deferred,
                iframe = document.createElement("iframe");
            return iframe.frameborder = 0, iframe.width = 1, iframe.height = 1, iframe.style.scrolling = "no", iframe.onload = function () {
                def.resolve()
            }, iframe.src = "//instaedu.go2cloud.org/SLA?amount=" + revAmt, document.body.appendChild(iframe), def
        },
        track = function (revAmt, callback) {
            var timeout = setTimeout(function () {
                callback()
            }, 3e3);
            $.when(loadBing(), loadHasOffers(revAmt), loadPerfectAudience(), loadAdwords(), loadMixpanel(), loadFacebook()).then(function () {
                clearTimeout(timeout), callback()
            })
        };
    return {
        track: track
    }
}), define("page-add-card", ["add-card/views"], function (page) {
    $(function () {
        new page.PageView({
            el: $("#card-container"),
            form: $("#profile-payment-form")
        })
    })
}), define("page-all", ["base/constants", "base/views", "base/connection-status", "config", "util"], function (constants, views, connectionStatus, config, util) {
    if (connectionStatus(), views.setupHeader(), views.setupUpcomingLesson(), window.ROLE = constants.ROLE, config.isAuthenticated && (!config.timezone || config.setTimezone)) {
        var tz = window.jstz.determine().name();
        tz && $.ajax({
            url: "/timezone/",
            type: "POST",
            data: {
                timezone: tz,
                csrfmiddlewaretoken: config.CSRF_TOKEN
            }
        }).done(function () {
            config.timezone = tz
        })
    }
    var $headerSearch = $("#header-search");
    $headerSearch.val($headerSearch.attr("value"));
    var SHARE_CONTEXT = constants.SHARE_CONTEXT,
        twitterShare = function (shareContext) {
            var url = null;
            switch (shareContext) {
            case SHARE_CONTEXT.Q_AND_A:
                url = "https://twitter.com/share?url=http%3A%2F%2Finstaedu.com%2Fqr%2F" + window.REFERRAL_CODE + "%2F&text=Just%20used%20a%20cool%20free%20service%20from%20@InstaEDU:%20Ask%20a%20Q%20about%20HW,%20get%20a%20great%20written%20explanation%20in%20a%20few%20hours.%20Try%20it:";
                break;
            case SHARE_CONTEXT.EXPLANATION:
                url = "https://twitter.com/share?url=http%3A%2F%2Finstaedu.com%2Fe%2F" + window.explanationCode + "%2F&text=I%20just%20helped%20someone%20with%20" + window.subjectKeywordUrlEscaped + "%20on%20@InstaEDU.%20Check%20out%20my%20explanation:";
                break;
            case SHARE_CONTEXT.LESSON:
                url = "https://twitter.com/share?url=http%3A%2F%2Finstaedu.com%2Fr%2F" + window.REFERRAL_CODE + "%2F&text=Check%20out%20@InstaEDU%20-%20a%20great%20way%20for%20students%20to%20get%20one-on-one%20help%20with%20classes.%20Try%20it%20free%20here:";
                break;
            default:
                url = "https://twitter.com/share?url=&text=" + encodeURIComponent($("#share-text").val())
            }
            var width = 575,
                height = 251,
                left = ($(window).width() - width) / 2,
                top = ($(window).height() - height) / 2,
                opts = "status=1,width=" + width + ",height=" + height + ",top=" + top + ",left=" + left;
            window.open(url, "twitter", opts)
        };
    $(".twitter-share").click(function () {
        return twitterShare(SHARE_CONTEXT.LESSON), !1
    }), $(".twitter-questions-share").click(function () {
        return twitterShare(SHARE_CONTEXT.Q_AND_A), !1
    }), $(".twitter-explanation-share").click(function () {
        return twitterShare(SHARE_CONTEXT.EXPLANATION), !1
    });
    var $storage = $("#ssl-storage");
    $storage.exists() && $storage.ready(function () {
        window.asyncStorage.build($storage[0])
    });
    var headerSearchInput = $("#header-search-container");
    $("#header-search-activate").click(function () {
        return headerSearchInput.show(), $("#header-search").focus(), !1
    }), $("#search-cancel").click(function () {
        return headerSearchInput.hide(), !1
    });
    var modernizrTouch = $("html").hasClass("touch");
    return modernizrTouch && $(document).on("focus", "input, textarea", function () {
        $("body").addClass("fixfixed")
    }).on("blur", "input, textarea", function () {
        $("body").removeClass("fixfixed")
    }), util.attachPopovers(), {
        twitterShare: twitterShare,
        $storage: $storage
    }
}), define("page-error-student-abandon", [], function () {
    var FormView = Backbone.View.extend({
        events: {
            "submit form": "submit"
        },
        initialize: function (opts) {
            this.$form = this.$("form"), this.submitURL = opts.submitURL, this.$linkSkipMessage = opts.$linkSkipMessage, this.$submitBtn = this.$("button.btn-primary")
        },
        disableBtn: function () {
            this.$submitBtn.addClass("disabled").prop("disabled", !0)
        },
        enableBtn: function () {
            this.$submitBtn.removeClass("disabled").prop("disabled", !1)
        },
        submit: function () {
            return this.$form.find("#message").val().trim() ? (this.$(".form-error").hide(), this.disableBtn(), $.ajax(this.submitURL, {
                type: "post",
                data: this.$form.serialize(),
                error: this.error.bind(this),
                success: this.success.bind(this)
            }), !1) : (this.$(".form-error").html("This field is required.").show(), !1)
        },
        error: function () {
            this.enableBtn(), this.$(".form-error").html("This field is required.").show()
        },
        success: function () {
            this.$linkSkipMessage.hide(), this.$form.hide(), this.$(".success").show()
        }
    });
    return {
        init: function (opts) {
            new FormView({
                el: opts.container,
                $linkSkipMessage: opts.$linkSkipMessage,
                submitURL: opts.submitURL
            })
        }
    }
}), window.loadSetUpVideo = function (nextURL) {
    var session, isConnected = !1,
        isStreamCreated = !1,
        VIDEO_STATE = {
            NOT_TESTED: 0,
            TOKBOX_FAIL: 1,
            SYSTEM_REQUIREMENTS_FAIL: 2,
            CONNECTION_FAIL: 3,
            NO_REMEMBER_FAIL: 4,
            NO_VIDEO_FAIL: 5,
            SUCCESS: 90,
            NOT_TESTED_LEGACY: 99
        },
        sessionConnectedHandler = function () {
            console.log("sessionConnectedHandler"), isConnected = !0, $("#remember-flash-arrow").show(), session.publish("test-video")
        },
        streamCreatedHandler = function () {
            console.log("streamCreatedHandler"), isStreamCreated = !0, $("#no-video").addClass("disabled").prop("disabled", !0), $("#remember-flash-arrow").hide(200, function () {
                $("#remember-flash").show(200)
            })
        },
        setVideoStateSuccess = function (data, state) {
            return state == VIDEO_STATE.SUCCESS && window.isExpertOnboarding ? (location.href = nextURL, void 0) : ($("#video-state-test").hide(200, function () {
                switch (state) {
                case VIDEO_STATE.SUCCESS:
                    $("#video-state-success").show(200);
                    break;
                case VIDEO_STATE.NO_REMEMBER_FAIL:
                    $("#video-state-no-remember-fail").show(200);
                    break;
                default:
                    $("#video-state-generic-fail").show(200)
                }
            }), void 0)
        },
        setVideoState = function (state) {
            var ts = (new Date).getTime().toString();
            $.ajax({
                url: window.SET_VIDEO_STATE_URL + "?_=" + ts,
                type: "POST",
                dataType: "json",
                data: {
                    state: state,
                    csrfmiddlewaretoken: window.CSRF_TOKEN
                },
                success: function (data) {
                    setVideoStateSuccess(data, state)
                },
                error: function () {
                    window.showErrorCatchall()
                }
            })
        },
        checkIsSessionConnected = function () {
            isConnected || setVideoState(VIDEO_STATE.CONNECTION_FAIL)
        };
    $("#yes-remember-flash").click(function () {
        $("#remember-flash").hide(200, function () {
            $("#video-ok-buttons").show(200, function () {
                setTimeout(function () {
                    $("#no-video").removeClass("disabled").removeAttr("disabled")
                }, 2e3)
            })
        })
    }), $("#no-remember-flash").click(function () {
        setVideoState(VIDEO_STATE.NO_REMEMBER_FAIL)
    }), $("#yes-video").click(function () {
        setVideoState(VIDEO_STATE.SUCCESS)
    }), $("#no-video").click(function () {
        this.disabled || setVideoState(VIDEO_STATE.NO_VIDEO_FAIL)
    }), $.ajax({
        url: "http://static.opentok.com/v1.1/js/TB.min.js",
        dataType: "script",
        cache: !0,
        success: function () {
            return window.TB.setLogLevel(window.TB.NONE), window.TB.checkSystemRequirements() ? (session = window.TB.initSession(window.sessionID), session.addEventListener("sessionConnected", sessionConnectedHandler), session.addEventListener("streamCreated", streamCreatedHandler), session.connect(window.apiKey, window.token), setTimeout(checkIsSessionConnected, 15e3), void 0) : (setVideoState(VIDEO_STATE.SYSTEM_REQUIREMENTS_FAIL), void 0)
        },
        error: function () {
            setVideoState(VIDEO_STATE.TOKBOX_FAIL)
        }
    })
}, define("direct-deposit", ["config"], function (config) {
    var FormView = Backbone.View.extend({
        events: {
            submit: "submit"
        },
        initialize: function (opts) {
            if (opts = opts || {}, this.submitURL = opts.submitURL || "", !this.submitURL) throw new Error("submitURL cannot be empty");
            if (this.redirectURL = opts.redirectURL || "", !this.redirectURL) throw new Error("redirectURL cannot be empty");
            this.isOnboarding = opts.isOnboarding || !1, this.$button = this.$('button[type="submit"]'), this.$stripeError = this.$(".stripe-error")
        },
        validate: function () {
            var valid = !0,
                country = this.$(".country").val(),
                routingNumber = this.$(".routing-number").val(),
                accountNumber = this.$(".account-number").val(),
                fullName = this.$(".full-name").val();
            return this.$(".error").html(""), window.Stripe.bankAccount.validateRoutingNumber(routingNumber, country) || (this.$(".routing-number-error").html("Invalid routing number"), valid = !1), window.Stripe.bankAccount.validateAccountNumber(accountNumber, country) || (this.$(".account-number-error").html("Invalid account number"), valid = !1), fullName || (this.$(".full-name-error").html("This field is required"), valid = !1), valid
        },
        submit: function () {
            return this.$button.prop("disabled", !0), this.validate() ? window.Stripe.bankAccount.createToken({
                country: this.$(".country").val(),
                routingNumber: this.$(".routing-number").val(),
                accountNumber: this.$(".account-number").val()
            }, function (status, data) {
                200 === status ? (this.$stripeError.hide(), $.post(this.submitURL, {
                    csrfmiddlewaretoken: config.CSRF_TOKEN,
                    isOnboarding: this.isOnboarding ? "1" : "0",
                    token: data.id,
                    fullName: this.$(".full-name").val()
                }).done(function () {
                    window.location = this.redirectURL
                }.bind(this)).fail(function (response) {
                    data = JSON.parse(response.responseText), data.errors && (data.errors.fullName && this.$(".full-name-error").html(data.errors.fullName), data.errors.token && this.$stripeError.html("Error: " + data.errors.token)), this.$button.prop("disabled", !1)
                }.bind(this))) : (this.$stripeError.html("Error: " + data.error.message).show(), this.$button.prop("disabled", !1))
            }.bind(this)) : this.$button.prop("disabled", !1), !1
        }
    });
    return {
        FormView: FormView
    }
}), define("page-subject-info", ["base/views", "experts/views", "util"], function (base, experts, util) {
    var ExpertListBottom = Backbone.Marionette.View.extend({
            ui: {
                relatedCourses: ".related-courses",
                relatedSubjects: ".related-subjects",
                relatedTopics: ".related-topics",
                revealMoreCourses: ".reveal-more-courses",
                revealMoreSubjects: ".reveal-more-subjects",
                revealMoreTopics: ".reveal-more-topics",
                hideMoreCourses: ".hide-more-courses",
                hideMoreSubjects: ".hide-more-subjects",
                hideMoreTopics: ".hide-more-topics"
            },
            events: {
                "click .reveal-more-courses": "showAllCourses",
                "click .reveal-more-subjects": "showAllSubjects",
                "click .reveal-more-topics": "showAllTopics",
                "click .hide-more-courses": "hideCourses",
                "click .hide-more-subjects": "hideSubjects",
                "click .hide-more-topics": "hideTopics"
            },
            initialize: function () {
                this.bindUIElements(), this.maxHeight = this.ui.relatedTopics.css("max-height")
            },
            showAllCourses: function () {
                this.ui.relatedCourses.css("max-height", "none"), this.ui.revealMoreCourses.hide(), this.ui.hideMoreCourses.show()
            },
            showAllSubjects: function () {
                this.ui.relatedSubjects.css("max-height", "none"), this.ui.revealMoreSubjects.hide(), this.ui.hideMoreSubjects.show()
            },
            showAllTopics: function () {
                this.ui.relatedTopics.css("max-height", "none"), this.ui.revealMoreTopics.hide(), this.ui.hideMoreTopics.show()
            },
            hideCourses: function () {
                this.ui.relatedTopics.css("max-height", this.maxHeight), this.ui.revealMoreCourses.show(), this.ui.hideMoreCourses.hide()
            },
            hideSubjects: function () {
                this.ui.relatedSubjects.css("max-height", this.maxHeight), this.ui.revealMoreSubjects.show(), this.ui.hideMoreSubjects.hide()
            },
            hideTopics: function () {
                this.ui.relatedTopics.css("max-height", this.maxHeight), this.ui.revealMoreTopics.show(), this.ui.hideMoreTopics.hide()
            }
        }),
        init = function (options) {
            var opts = options || {},
                isResultsPage = opts.isResultsPage || !1,
                subjectID = opts.subjectID,
                $filterForm = $(".filter-form");
            $(function () {
                $("#jump-to-subjects").click(function () {
                    var offset = $("#subjects").offset(),
                        top = offset.top - 10 - $("#top-nav").height();
                    return $("html, body").animate({
                        scrollTop: top + "px"
                    }, 400), !1
                }), $(".subject-message-form").each(function () {
                    new experts.MessageForm({
                        el: $(this),
                        $filterForm: $filterForm
                    })
                }), isResultsPage && (new experts.ResultsPageView({
                    el: $("#subject-page"),
                    $filterForm: $filterForm,
                    keywordView: new experts.TagFieldView({
                        el: $filterForm.find(".keywords"),
                        $filterForm: $filterForm
                    }),
                    subjectView: new experts.SubjectFieldView({
                        el: $filterForm.find(".subjects"),
                        $filterForm: $filterForm,
                        subjectID: subjectID
                    })
                }), new experts.ModalMessageForm({
                    el: "#subject-message-form",
                    $filterForm: $filterForm
                })), new experts.FFMSubjectView({
                    el: "#ffm-subject-container",
                    $filterForm: $filterForm
                }), $(".how-does-this-work").on("click", function () {
                    $("#how-does-this-work-modal").modal("show"), new experts.FFMSubjectView({
                        el: ".hdtw-subject-container",
                        $filterForm: $filterForm
                    })
                }), experts.mobileFilters(), Backbone.history.navigate(location.search, {
                    trigger: !0
                });
                var $container = $(".expert-container").last();
                if ($container.exists()) {
                    var bannerHeight = $("#upcoming-lesson-banner").outerHeight();
                    util.affixAndHold($("#subject-fixed-box"), $container, bannerHeight)
                }
                new ExpertListBottom({
                    el: ".expert-list-bottom"
                })
            })
        };
    return init
}), define("page-start-search", [], function () {
    var View = Backbone.View.extend({
            events: {
                "click .start-search": "startSearch"
            },
            startSearch: function () {
                return window.createLesson(_.extend({
                    searchQueryString: "",
                    lastLessonCode: null,
                    isForwardedFrom: !1
                }, this.$el.serializeHash())), !1
            }
        }),
        shiftPaused = function () {};
    return {
        init: function () {
            new View({
                el: $(".session-form")
            }), $("fieldset > h4").click(function () {
                setTimeout(shiftPaused, 250)
            }), $(window).resize(shiftPaused), shiftPaused()
        }
    }
}), define("page-payment-info", ["util"], function (util) {
    var DowngradeSurveyForm = Backbone.View.extend({
            events: {
                "click #submit-downgrade-survey": "submitDowngradeSurvey"
            },
            submitDowngradeSurvey: function (event) {
                var $form = this.$el.find("#downgrade-survey"),
                    $reasons = $form.find("[name=reasons]"),
                    reasons = $("[name=reason]:checked").map(function () {
                        return this.value
                    }).get().join();
                $reasons.val(reasons), util.API.formSubmit($form, event, {
                    redirects: !0,
                    endpoint: "feedback/submit_survey/",
                    ajaxOptions: {
                        success: function (data) {
                            location.href = data.redirectURL ? data.redirectURL : "/"
                        }
                    }
                })
            },
            initialize: function () {
                this.$el.modal("show")
            }
        }),
        ChangeCommitmentForm = Backbone.View.extend({
            events: {
                "click .free-trial-choice": "chooseFreeTrial",
                "click #submit-commitment-form": "submitAgreementForm"
            },
            submitAgreementForm: function (event) {
                return util.API.formSubmit(this.$el, event, {
                    endpoint: location.href,
                    redirects: !0,
                    ajaxOptions: {
                        success: function (data) {
                            data.canceledCommitment ? new DowngradeSurveyForm({
                                el: $("#downgrade-survey-modal")
                            }) : location.href = data.redirectURL
                        }
                    }
                }), !1
            },
            chooseFreeTrial: function (event) {
                $("input[name=agreement-type]").each(function (index, elem) {
                    $(elem).parent().parent().removeClass("selected")
                });
                var $current = $(event.currentTarget);
                $current.addClass("selected"), $current.find(":radio").prop("checked", !0), $(".discount-time-string").html($current.attr("data-discount-time")), $(".setup-fee-string").html($current.attr("data-setup-fee")), $(".setup-fee-dollars-string").html($current.attr("data-setup-fee-dollars")), $(".discount-time-label").html($current.attr("data-discount-label")), $(".bill-at-start-adj").html($current.attr("data-bill-at-start-adj"))
            },
            initialize: function () {
                $("#id_expiration_date_month").val(_.sprintf("%02d", (new Date).getMonth() + 1))
            }
        });
    return {
        changeCommitmentForm: ChangeCommitmentForm,
        downgradeSurveyForm: DowngradeSurveyForm
    }
}), define("page-inbox", ["socket", "inbox/views"], function (socket, inbox) {
    var init = function (opts) {
        var userID = opts.userID,
            alertElem = opts.alertElem,
            myInbox = inbox.setupInbox({
                view: inbox.InboxView,
                loadMoreURL: opts.loadMoreURL,
                startID: opts.startID,
                moreToLoad: opts.moreToLoad
            }),
            messageRoom = "user=" + userID,
            alertView = new inbox.NewMessageAlertView({
                el: alertElem,
                inbox: myInbox
            });
        socket.emit("subscribeTo", messageRoom), socket.on("reconnect", function () {
            socket.emit("subscribeTo", messageRoom)
        }), socket.on("inbox:new.message", function (data) {
            myInbox.renderMessage(data), alertView.incrementCount().render().show()
        })
    };
    return {
        init: init
    }
}), define("sign-up", function () {
    var loadSignUp = function () {
            var $pageCreateAcctBtn = $(".js-account-create"),
                $pageFacebookCreate = $(".js-fb-create"),
                onFocus = function (e) {
                    $(e.currentTarget).removeClass("error")
                },
                validatorCallback = function (errors) {
                    if (errors.length > 0) {
                        for (var errorString = "", i = 0, errorLength = errors.length; errorLength > i; i++) $("#" + errors[i].id).addClass("error").focus(onFocus), errorString += errors[i].message + "<br />";
                        $("#page-sign-up-form").find(".form-errors").html(errorString).slideDown(150)
                    } else $pageCreateAcctBtn.button("loading")
                },
                fbValidatorCallback = function (errors) {
                    if (errors.length > 0) {
                        for (var errorString = "", i = 0, errorLength = errors.length; errorLength > i; i++) $("#" + errors[i].id).addClass("error").focus(onFocus), errorString += errors[i].message + "<br />";
                        return $("#page-facebook-addtl-form").find(".form-errors").hide().html(errorString).slideDown(150), !1
                    }
                    $pageFacebookCreate.button("loading")
                },
                validator = new window.FormValidator("page-sign-up-form", [{
                    name: "name",
                    rules: "required|min_length[2]|callback_check_name"
                }, {
                    name: "select-user-role",
                    rules: "required"
                }, {
                    name: "email",
                    rules: "required|valid_email"
                }, {
                    name: "password",
                    rules: "required|min_length[6]"
                }], validatorCallback);
            validator.registerCallback("check_name", function (value) {
                for (var names = value.split(" "), i = 0; i < names.length; i++)
                    if (names[i].length < 2 || /[0-9]+/i.test(names[i])) return !1;
                return !0
            }), validator.setMessage("check_name", "Your first or last name is invalid.");
            var fbValidator = new window.FormValidator("page-facebook-addtl-form", [{
                name: "role",
                rules: "required"
            }, {
                name: "password",
                rules: "required|min_length[6]"
            }], fbValidatorCallback);
            fbValidator.setMessage("required", "Please set a %s for your account")
        },
        parentInit = function () {
            var $parentRadio = $(".radio-btn-pair input[type=radio]").eq(1);
            $parentRadio.prop("checked", !0)
        };
    return {
        loadSignUp: loadSignUp,
        parentInit: parentInit
    }
}), define("events", ["config"], function (config) {
    var EVENT = {
        REALTIME_CONNECTION_CHANGED: 100,
        AVAILABLE_NOW_CHANGED: 1001,
        AVAILABLE_NOW_STILL_AVAILABLE: 1002,
        AVAILABLE_NOW_SETTING_CHANGED: 1003,
        AVAILABLE_NOW_DONT_SHOW_MODAL: 1004,
        AVAILABLE_NOW_SEARCH_CHANGED: 1010,
        MEET_NOW_REQUEST_SENT: 1100,
        LESSON_CHOOSE_AV_ACCESS: 1101,
        TOKBOX_VIDEO_TOGGLE: 1102,
        TOKBOX_AUDIO_TOGGLE: 1103,
        WRITTEN_LESSON_FOR_TUTOR_REQUEST: 1200,
        AUDIOBRIDGE_CONFERENCE_CALL_CONNECT: 1300,
        AUDIOBRIDGE_CONFERENCE_INFO_INITIATE: 1301,
        AUDIOBRIDGE_CONFERENCE_INFO_RECEIVE: 1302,
        REGISTRATION_SIGNUP_MODAL_OPENED: 1400,
        SUPPORT_AUTOMATED_MESSAGE: 1500,
        SUPPORT_MESSAGE_BLAST_MODAL: 1501,
        MESSAGE_TUTOR: 1601,
        PHRASEBANK_OPEN: 1700,
        PHRASEBANK_CLICK_PHRASE: 1701,
        CYCLE_CHAT_WINDOWS: 1800
    };
    return {
        EVENT: EVENT,
        create: function (type, data) {
            return $.ajax({
                url: "/api/event/",
                type: "POST",
                data: {
                    csrfmiddlewaretoken: config.CSRF_TOKEN,
                    type: type,
                    path: window.location.pathname + window.location.search,
                    data: data ? JSON.stringify(data) : null
                }
            })
        }
    }
}), define("paper", function () {
    var paper, papers = {};
    return {
        paper: paper,
        papers: papers,
        setup: function (canvasID) {
            return canvasID in papers ? papers[canvasID] : (papers[canvasID] = window.paper.setup(canvasID), paper || (paper = papers[canvasID]), papers[canvasID])
        }
    }
}), define("util", ["config", "rollbar"], function (config, rollbar) {
    var BaseModel = Backbone.Model.extend({
            destroy: function () {
                this.trigger("destroy")
            }
        }),
        BaseView = Backbone.View.extend({
            initialize: function (options) {
                this.setDefaults(options), this.postInit(options)
            },
            postInit: function () {},
            setDefaults: function () {}
        }),
        GlobalEventModal = Backbone.View.extend({
            eventEl: "body",
            initialize: function (options) {
                this.namespace = options.namespace || "", this.namespace && (this.namespace = "." + this.namespace), this.started = !1, this.$eventEl = $(this.eventEl)
            },
            start: function () {
                this.started || (this.bindEvent(), this.started = !0)
            },
            stop: function () {
                this.started && (this.$eventEl.unbind(this.namespace), this.started = !1)
            },
            show: function () {
                return this.$el.modal("show"), !1
            },
            bindEvent: function () {}
        }),
        PageLeaveModal = GlobalEventModal.extend({
            eventEl: window,
            initialize: function (options) {
                GlobalEventModal.prototype.initialize.apply(this, arguments), this.message = options.message
            },
            bindEvent: function () {
                this.$eventEl.on("beforeunload" + this.namespace, function (event) {
                    return (event || window.event).returnValue = this.message, this.message
                }.bind(this))
            }
        }),
        BackspaceModal = GlobalEventModal.extend({
            events: {
                "click .go-back": "goBack"
            },
            goBack: function () {
                window.history.back()
            },
            bindEvent: function () {
                var textFields = ["input[type=text]", "input[type=password]", "input[type=file]", "textarea", "canvas"];
                this.$eventEl.on("keydown" + this.namespace, function (event) {
                    return event.keyCode != Event.KEY_BACK_SPACE || $(event.target).is(textFields.join(",")) ? void 0 : this.show()
                }.bind(this))
            }
        }),
        DiffTimer = Backbone.View.extend({
            initialize: function (options) {
                this.seconds = 0, this.interval = null, this.endCallback = options.endCallback || function () {}, this.showHours = options.showHours === !1 ? !1 : !0, this.showSeconds = !!options.showSeconds, this.useDelimiter = !!options.useDelimiter, this.$el.attr("data-seconds") && this.start()
            },
            start: function () {
                this.end(), this.seconds = parseInt(this.$el.attr("data-seconds"), 10), setInterval(this.tick.bind(this), 1e3)
            },
            end: function (runCallback) {
                clearInterval(this.interval), runCallback && this.endCallback()
            },
            tick: function () {
                if (--this.seconds < 0) return this.seconds = 0, void 0;
                var hours = Math.floor(this.seconds / 3600),
                    minutes = Math.floor(this.seconds / 60) % 60,
                    seconds = this.seconds % 60,
                    countdown = "";
                this.showHours && (countdown += _.sprintf("%02d", hours), countdown += this.useDelimiter ? ":" : "h"), countdown += _.sprintf("%02d", minutes), this.useDelimiter || (countdown += "m"), this.showSeconds && (this.useDelimiter && (countdown += ":"), countdown += _.sprintf("%02d", seconds), this.useDelimiter || (countdown += "s")), this.$el.html(countdown), 0 === this.seconds && this.end(!0)
            }
        }),
        TextCounter = Backbone.View.extend({
            events: {
                keydown: "refresh"
            },
            initialize: function (options) {
                this.limit = options.limit, this.$counter = options.$counter, this.callback = options.callback || function () {}, setInterval(this.refresh.bind(this), 100)
            },
            refresh: function () {
                var avail = this.getAvailableCharacters();
                this.$counter.text(avail)[avail >= 0 ? "removeClass" : "addClass"]("negative"), this.callback(avail)
            },
            getAvailableCharacters: function () {
                return this.limit - this.$el.val().length
            }
        }),
        _ajaxCalls = {},
        _makeAjaxCall = function (options) {
            var defaults = {
                cache: !1,
                ajaxCall: null,
                checkDataForDoubleSubmit: !1
            };
            options = _.extend(defaults, options);
            var empty = function () {},
                success = options.success || empty,
                error = options.error || empty,
                complete = options.complete || empty,
                parseJSONResponse = function (xhr) {
                    var response = xhr.responseText;
                    return "application/json" == xhr.getResponseHeader("content-type") && (response = $.parseJSON(response)), response
                };
            if (options.success = function (data, textStatus, xhr) {
                success(data, textStatus, xhr)
            }, options.error = function (xhr, textStatus, errorThrown) {
                error(parseJSONResponse(xhr), xhr, textStatus, errorThrown)
            }, options.complete = function (xhr, textStatus) {
                delete _ajaxCalls[options.url], complete(parseJSONResponse(xhr), xhr, textStatus)
            }, options.statusCode && _(options.statusCode).each(function (callback, code) {
                options.statusCode[code] = function (xhr, textStatus, errorThrown) {
                    callback(parseJSONResponse(xhr), xhr, textStatus, errorThrown)
                }
            }), options.csrf && (options.data = options.data || {}, _.isObject(options.data) ? options.data.csrfmiddlewaretoken = config.CSRF_TOKEN : options.data += "&csrfmiddlewaretoken=" + config.CSRF_TOKEN), options.url in _ajaxCalls && (!options.checkDataForDoubleSubmit || _.isEqual(options.data, _ajaxCalls[options.url]))) return console.warn("double submit to " + options.url), (new $.Deferred).resolve();
            _ajaxCalls[options.url] = options.data;
            var ajaxCall = $.ajax;
            return options.ajaxCall && (ajaxCall = options.ajaxCall), _.each(defaults, function (d) {
                delete options[d]
            }), ajaxCall(options)
        },
        API = function (baseURL) {
            this.baseURL = baseURL
        };
    _.extend(API.prototype, {
        getFullURL: function (url) {
            var regex = new RegExp("^" + this.baseURL, "i");
            return regex.test(url) ? url : this.baseURL + _.ltrim(url, "/")
        },
        get: function (url, options) {
            return _makeAjaxCall(_.extend(options || {}, {
                url: this.getFullURL(url),
                type: "GET"
            }))
        },
        post: function (url, options) {
            return _makeAjaxCall(_.extend(options || {}, {
                url: this.getFullURL(url),
                type: "POST"
            }))
        },
        formSubmit: function ($form, event, options) {
            event.preventDefault(), options = options || {};
            var $btn = options.$btn || $form.find(".btn-primary"),
                $errors = options.$errors || $form.find(".form-error"),
                $inputs = options.$inputs || $form.find(":input"),
                callback = options.callback || this.post.bind(this),
                data = options.data || $form.serialize(),
                ajaxOptions = options.ajaxOptions || {},
                success = ajaxOptions.success || function () {},
                error = ajaxOptions.error || function () {},
                complete = ajaxOptions.complete || function () {};
            ajaxOptions.url || (ajaxOptions.url = $form.attr("action"));
            var removeErrors = function () {
                $errors.empty().hide(), $inputs.removeClass("error")
            };
            _.extend(ajaxOptions, {
                success: function (data, textStatus, xhr) {
                    removeErrors(), success(data, textStatus, xhr)
                },
                error: function (response, xhr, textStatus, errorThrown) {
                    removeErrors();
                    var prefix = response.prefix || $form.find("input[name=prefix]").val();
                    prefix = prefix ? prefix + "-" : "", _.each(response.errors, function (errors, name) {
                        if (_.isArray(errors)) {
                            var $ul = $("#" + prefix + name + "-error");
                            _.each(errors, function (error) {
                                $ul.append($("<li/>").html(error))
                            }), $ul.show(), $form.find("[name=" + prefix + name + "]").addClass("error")
                        }
                    }), error(response, xhr, textStatus, errorThrown)
                },
                complete: function (response, xhr, textStatus) {
                    "success" == textStatus && options.redirects || $btn.button("reset"), complete(response, xhr, textStatus)
                }
            }), $btn.button("loading"), options.endpoint ? callback(options.endpoint, _.extend({
                data: data
            }, ajaxOptions), $form) : callback(_.extend({
                data: data
            }, ajaxOptions), $form)
        }
    });
    var Event = {
            KEY_CANCEL: 3,
            KEY_HELP: 6,
            KEY_BACK_SPACE: 8,
            KEY_TAB: 9,
            KEY_CLEAR: 12,
            KEY_RETURN: 13,
            KEY_ENTER: 14,
            KEY_SHIFT: 16,
            KEY_CONTROL: 17,
            KEY_ALT: 18,
            KEY_PAUSE: 19,
            KEY_CAPS_LOCK: 20,
            KEY_ESCAPE: 27,
            KEY_SPACE: 32,
            KEY_PAGE_UP: 33,
            KEY_PAGE_DOWN: 34,
            KEY_END: 35,
            KEY_HOME: 36,
            KEY_LEFT: 37,
            KEY_UP: 38,
            KEY_RIGHT: 39,
            KEY_DOWN: 40,
            KEY_PRINTSCREEN: 44,
            KEY_INSERT: 45,
            KEY_DELETE: 46,
            KEY_0: 48,
            KEY_1: 49,
            KEY_2: 50,
            KEY_3: 51,
            KEY_4: 52,
            KEY_5: 53,
            KEY_6: 54,
            KEY_7: 55,
            KEY_8: 56,
            KEY_9: 57,
            KEY_SEMICOLON: 59,
            KEY_EQUALS: 61,
            KEY_A: 65,
            KEY_B: 66,
            KEY_C: 67,
            KEY_D: 68,
            KEY_E: 69,
            KEY_F: 70,
            KEY_G: 71,
            KEY_H: 72,
            KEY_I: 73,
            KEY_J: 74,
            KEY_K: 75,
            KEY_L: 76,
            KEY_M: 77,
            KEY_N: 78,
            KEY_O: 79,
            KEY_P: 80,
            KEY_Q: 81,
            KEY_R: 82,
            KEY_S: 83,
            KEY_T: 84,
            KEY_U: 85,
            KEY_V: 86,
            KEY_W: 87,
            KEY_X: 88,
            KEY_Y: 89,
            KEY_Z: 90,
            KEY_CONTEXT_MENU: 93,
            KEY_NUMPAD0: 96,
            KEY_NUMPAD1: 97,
            KEY_NUMPAD2: 98,
            KEY_NUMPAD3: 99,
            KEY_NUMPAD4: 100,
            KEY_NUMPAD5: 101,
            KEY_NUMPAD6: 102,
            KEY_NUMPAD7: 103,
            KEY_NUMPAD8: 104,
            KEY_NUMPAD9: 105,
            KEY_MULTIPLY: 106,
            KEY_ADD: 107,
            KEY_SEPARATOR: 108,
            KEY_SUBTRACT: 109,
            KEY_DECIMAL: 110,
            KEY_DIVIDE: 111,
            KEY_F1: 112,
            KEY_F2: 113,
            KEY_F3: 114,
            KEY_F4: 115,
            KEY_F5: 116,
            KEY_F6: 117,
            KEY_F7: 118,
            KEY_F8: 119,
            KEY_F9: 120,
            KEY_F10: 121,
            KEY_F11: 122,
            KEY_F12: 123,
            KEY_F13: 124,
            KEY_F14: 125,
            KEY_F15: 126,
            KEY_F16: 127,
            KEY_F17: 128,
            KEY_F18: 129,
            KEY_F19: 130,
            KEY_F20: 131,
            KEY_F21: 132,
            KEY_F22: 133,
            KEY_F23: 134,
            KEY_F24: 135,
            KEY_NUM_LOCK: 144,
            KEY_SCROLL_LOCK: 145,
            KEY_EQUAL_SIGN: 187,
            KEY_COMMA: 188,
            KEY_DASH: 189,
            KEY_PERIOD: 190,
            KEY_SLASH: 191,
            KEY_BACK_QUOTE: 192,
            KEY_OPEN_BRACKET: 219,
            KEY_BACK_SLASH: 220,
            KEY_CLOSE_BRACKET: 221,
            KEY_QUOTE: 222,
            KEY_META: 224
        },
        scrollLock = function ($el, infinite) {
            var atTheStart = !1,
                atTheEnd = !1,
                wheelStop = function (event) {
                    var up = event.wheel() >= 0;
                    (atTheStart && up || atTheEnd && !up) && (event.stopPropagation(), event.preventDefault())
                },
                toInfinityAndBeyond = function (event) {
                    var $target = $(event.target),
                        scrollTop = $target.scrollTop(),
                        scrollPos = scrollTop + $target.height();
                    atTheStart = 0 >= scrollTop, atTheEnd = scrollPos >= $target.prop("scrollHeight"), atTheEnd && _.isFunction(infinite) && infinite(event)
                };
            $el.off(".scrollLock"), $el.on("scroll.scrollLock", toInfinityAndBeyond), $el.on("mousewheel.scrollLock", wheelStop), $el.on("DOMMouseScroll.scrollLock", wheelStop)
        },
        highlight = function ($el) {
            $el.effect("highlight", {
                color: "#E2EDF4"
            }, 250)
        },
        FormDateHelper = function (firstMonth, minutesOffset) {
            var date = new Date;
            minutesOffset = _.isUndefined(minutesOffset) ? 1440 : minutesOffset, date.setMinutes(date.getMinutes() + minutesOffset);
            var currentOffset = -1 * date.getTimezoneOffset() / 60;
            this.offset = currentOffset - config.UTC_OFFSET, date.setHours(date.getHours() - this.offset), this.currentMonth = date.getMonth() + 1, this.currentDay = date.getDate(), this.currentYear = date.getFullYear(), this.firstMonth = parseInt(firstMonth || 0, 10), this.date = date
        };
    _.extend(FormDateHelper.prototype, {
        formatTimeData: function (month, day, hour, minute, second) {
            var year = this.currentYear;
            month = parseInt(month, 10);
            var endofyear = -1 != $.inArray(this.firstMonth, [11, 12]);
            return !endofyear || 1 != month && 2 != month || year++, _.sprintf("%04d-%02d-%02d %02d:%02d:%02d", year, month, parseInt(day, 10), parseInt(hour, 10), parseInt(minute || 0, 10), parseInt(second || 0, 10))
        }
    });
    var CollapsableMenu = Backbone.View.extend({
            events: {
                "click .tips-toggle": "toggleExpand"
            },
            toggleExpand: function (event) {
                var $this = $(event.target);
                $this.hasClass("expanded") ? ($this.removeClass("expanded"), $this.parent().parent().find("ul").hide()) : ($this.addClass("expanded"), $this.parent().parent().find("ul").show())
            }
        }),
        getTimezoneOffset = function (theirOffsetMinutes) {
            var myOffsetMinutes = config.timezoneOffsetMinutes || -(new Date).getTimezoneOffset(),
                offsetDifferenceStr = "User's timezone is unknown";
            if (!_.isUndefined(theirOffsetMinutes) && !_.isNull(theirOffsetMinutes)) {
                var unit, str, offsetDifference = (theirOffsetMinutes - myOffsetMinutes) / 60;
                if (unit = 1 === Math.abs(offsetDifference) ? "hr" : "hrs", 0 === offsetDifference) return "You are in the same timezone";
                str = 0 > offsetDifference ? "behind you" : "ahead of you", offsetDifferenceStr = _.sprintf("Timezone: %f %s %s", Math.abs(offsetDifference), unit, str)
            }
            return offsetDifferenceStr
        },
        dateFormatPrettyfier = function (isoDate) {
            if (!isoDate) return "--";
            var now = window.moment.utc(),
                lessonDate = window.moment.utc(isoDate);
            return now.isSame(lessonDate, "day") ? "Today" : now.isSame(lessonDate, "year") ? lessonDate.local().format("MMM D") : lessonDate.local().format("MM/DD/YY")
        },
        topNavHeight = $("#header").height(),
        $howitworksPanel = $("#howitworks-panel"),
        getHowItWorksHeight = function () {
            return $howitworksPanel.is(":visible") ? $howitworksPanel.outerHeight() : 0
        },
        getTopHeight = function () {
            return topNavHeight + getHowItWorksHeight()
        },
        getQueryVariable = function (variable) {
            for (var query = window.location.search.substring(1), vars = query.split("&"), i = 0; i < vars.length; i++) {
                var pair = vars[i].split("=");
                if (pair[0] == variable) return pair[1]
            }
            return !1
        },
        getMinTime = function (options) {
            options = options || {};
            var minTime = options.customDate ? new Date(options.customDate) : new Date,
                nextMinute = options.meetNow ? minTime.getMinutes() : 15 * Math.ceil(minTime.getMinutes() / 15);
            return null !== config.timezoneOffsetMinutes ? minTime.setMinutes(nextMinute + config.timezoneOffsetMinutes + minTime.getTimezoneOffset()) : minTime.setMinutes(nextMinute), minTime
        },
        getDatetimeString = function ($datepicker, $timepicker) {
            var date = new Date($datepicker.val()),
                time = $timepicker.val();
            "End of Day" === time && (time = "11:59pm");
            var timeString = "",
                timeRegex = /([0-9]{1,2}):([0-9]{2})\s?([apAP][Mm])/,
                timeParts = timeRegex.exec(time);
            if (null !== timeParts) {
                var hour = parseInt(timeParts[1], 10),
                    minute = parseInt(timeParts[2], 10),
                    period = timeParts[3].toUpperCase();
                hour = 12 == hour ? 0 : hour;
                var hour24 = "PM" === period ? hour + 12 : hour;
                timeString = _.sprintf("%04d-%02d-%02d %02d:%02d:%02d", date.getFullYear(), date.getMonth() + 1, date.getDate(), hour24, minute, 0)
            }
            return timeString
        };
    return {
        API: new API(config.isSSL ? config.BASE_SSL_URL : config.BASE_URL),
        Event: Event,
        BaseModel: BaseModel,
        BaseView: BaseView,
        BackspaceModal: BackspaceModal,
        PageLeaveModal: PageLeaveModal,
        GlobalEventModal: GlobalEventModal,
        DiffTimerView: DiffTimer,
        TextCounter: TextCounter,
        FormDateHelper: FormDateHelper,
        CollapsableMenu: CollapsableMenu,
        scrollLock: scrollLock,
        topNavHeight: topNavHeight,
        highlight: highlight,
        getTopHeight: getTopHeight,
        getHowItWorksHeight: getHowItWorksHeight,
        getTimezoneOffset: getTimezoneOffset,
        dateFormatPrettyfier: dateFormatPrettyfier,
        getQueryVariable: getQueryVariable,
        getMinTime: getMinTime,
        getDatetimeString: getDatetimeString,
        triggerOnGlobalClick: function (rebindCallback, clickCallback, options) {
            options = options || {};
            var eventName = "click";
            options.namespace && (eventName += "." + options.namespace);
            var removeClick = function () {
                $(document).one(eventName, function (event) {
                    var $target = $(event.target);
                    return rebindCallback($target, event) ? (removeClick(), !0) : _.isFunction(options.ignoreCallback) && options.ignoreCallback($target, event) ? !0 : (clickCallback($target, event), void 0)
                })
            };
            removeClick()
        },
        attachPopovers: function ($container) {
            var $popovers = $container ? $container.hasClass("js-popover") ? $container : $container.find(".js-popover") : $(".js-popover");
            $popovers.each(function () {
                var $this = $(this);
                $this.popover(_.extend({
                    html: !0,
                    trigger: "hover",
                    container: "body",
                    title: function () {
                        return $this.children(".js-popover-title").html()
                    },
                    content: function () {
                        return $this.children(".js-popover-content").html()
                    }
                }, $this.data()))
            })
        },
        flashClass: function ($el, className, duration) {
            duration = duration || 500, $el.addClass(className), setTimeout(function () {
                $el.removeClass(className)
            }, duration)
        },
        focusAndHighlight: function ($el) {
            highlight($el), $el.focus()
        },
        scrollTop: function (top, offset) {
            offset = offset || 0, $("body, html").animate({
                scrollTop: top - topNavHeight - offset + "px"
            })
        },
        scrollToElement: function (selector, correction, duration) {
            correction = correction || 0, duration = duration || 1e3;
            var offset = $(selector).offset().top - correction;
            $("body, html").animate({
                scrollTop: offset
            }, duration)
        },
        affixAndHold: function ($el, $endContainer, topOffset, padding) {
            if ($el.exists()) {
                topOffset = topOffset || 0;
                var initialTop = $el.position().top,
                    initialContainerTop = $endContainer.offset().top;
                $el.affix({
                    offset: {
                        top: function () {
                            return initialTop + topOffset + getHowItWorksHeight()
                        },
                        hold: function () {
                            return initialContainerTop + getHowItWorksHeight() + $endContainer.height() - $el.outerHeight() - topNavHeight
                        },
                        padding: padding
                    }
                })
            }
        },
        isEnterKey: function (event) {
            return $.inArray(event.keyCode, [Event.KEY_ENTER, Event.KEY_RETURN]) > -1
        },
        makeDeferred: function (obj) {
            var d = new $.Deferred;
            _.each(_.functions(d), function (fun) {
                obj[fun] = _.bind(d[fun], d)
            })
        },
        fileUpload: function ($form, options) {
            options = options || {};
            var $fileInput = $form.find("input:file"),
                $progressContainer = $form.find(".progress"),
                $progressBar = $form.find(".progress .bar"),
                emptyFn = function () {},
                callbacks = {
                    before: {},
                    after: {}
                },
                useVisibility = "hidden" == $progressBar.css("visibility");
            _.each(["change", "add", "fail", "always", "progress"], function (cb) {
                _.each(["before", "after"], function (when) {
                    var optKey = when + _.ucfirst(cb);
                    _.isFunction(options[optKey]) ? (callbacks[when][cb] = options[optKey], delete options[optKey]) : callbacks[when][cb] = emptyFn
                })
            });
            var formData = _.extend({
                csrfmiddlewaretoken: config.CSRF_TOKEN
            }, options.formData);
            delete options.formData, options.url || (options.url = $form.attr("action"));
            var uploadDeferred = null;
            $fileInput.fileupload(_.extend({
                dataType: "json",
                formData: formData,
                replaceFileInput: !1,
                dropZone: null,
                pasteZone: null,
                change: function (e, data) {
                    callbacks.before.change(e, data);
                    var fileName = _.last($fileInput.val().split(/[\\/]/));
                    data.context = {
                        fileName: fileName,
                        ext: _.strRightBack(fileName, "."),
                        hasAttachment: !_.isBlank(fileName)
                    }, uploadDeferred = new $.Deferred, $progressBar.css("width", "0%").text("Uploading..."), useVisibility ? $progressContainer.css("visibility", "hidden") : $progressContainer.hide(), callbacks.after.change(e, data)
                },
                add: function (e, data) {
                    callbacks.before.add(e, data), data.submit(), callbacks.after.add(e, data)
                },
                fail: function (e, data) {
                    callbacks.before.fail(e, data);
                    var status = data.jqXHR.status,
                        text = data.jqXHR.responseText || "",
                        response = text.match(/^\{/) ? JSON.parse(data.jqXHR.responseText) : {},
                        loginRequired = "login_required" == response.error;
                    if (rollbar.log("Failed file upload. Status: " + status + (loginRequired ? " [login_required]" : "")), $fileInput.val(""), !options.hideErrorModals) switch (status) {
                    case 400:
                        $("#bad-attachment-modal").modal("show");
                        break;
                    case 0:
                    case 413:
                        $("#large-attachment-modal").modal("show");
                        break;
                    case 404:
                        loginRequired && location.reload()
                    }
                    callbacks.after.fail(e, data)
                },
                always: function (e, data) {
                    callbacks.before.always(e, data), uploadDeferred.always(function () {
                        $progressBar.text("Upload complete!")
                    }), _.delay(function () {
                        $progressContainer.fadeOut("slow", function () {
                            useVisibility && $progressContainer.css("visibility", "hidden").show()
                        })
                    }, 1e3), callbacks.after.always(e, data)
                },
                progress: function (e, data) {
                    callbacks.before.progress(e, data);
                    var progress = parseInt(100 * (data.loaded / data.total), 10);
                    useVisibility ? $progressContainer.css("visibility", "visible") : $progressContainer.show(), $progressBar.css("width", progress + "%"), progress >= 100 && uploadDeferred.resolve(), callbacks.after.progress(e, data)
                }
            }, options))
        }
    }
}), define("page-choose-subjects", ["util"], function (util) {
    $("fieldset > h2").click(function () {
        var $this = $(this),
            $plus = $this.children("a:first");
        return $this.toggleClass("expanded").parent().children("div").toggle(200), $plus.html("+" == $plus.html() ? "-" : "+"), !1
    });
    var SubmitSubjectsForm = Backbone.View.extend({
        events: {
            "click button": "submitSubjectsForm",
            "change .all-checkbox input:checkbox": "toggleAll",
            "change .row input:checkbox": "toggleAllCheckbox"
        },
        submitSubjectsForm: function (event) {
            return util.API.formSubmit(this.$el, event, {
                endpoint: location.href,
                redirects: !0,
                ajaxOptions: {
                    success: function (data) {
                        location.href = data.redirectURL
                    },
                    error: function () {
                        $("#choose-subjects-error-modal").modal("show")
                    }
                }
            }), !1
        },
        toggleAll: function (event) {
            var $checkbox = $(event.target),
                id = $checkbox.prop("id"),
                state = $checkbox.is(":checked");
            this.$("[data-group-id=" + id + "] input:checkbox").each(function () {
                $(this).prop("checked", state)
            })
        },
        toggleAllCheckbox: function (event) {
            var $row = $(event.target).closest(".row"),
                id = $row.attr("data-group-id"),
                on = _.every($row.find("input:checkbox"), function (input) {
                    return $(input).is(":checked")
                });
            $("#" + id).prop("checked", on)
        }
    });
    return {
        submitSubjectsForm: SubmitSubjectsForm
    }
}), define("rollbar", ["config"], function (config) {
    var push = function (args) {
            for (var message = {
                level: "debug",
                msg: args[0]
            }, i = 1; i < args.length; i++) message[i] = args[i];
            window._rollbar.push(message)
        },
        _console = function (method, args) {
            if (!config.IS_PROD)
                if (method.apply) method.apply(console, args);
                else
                    for (var i = 0; i < args.length; i++) method(args[i])
        };
    return {
        log: function () {
            _console(console.log, arguments), push(arguments)
        },
        warn: function () {
            _console(console.warn, arguments), push(arguments)
        },
        error: function () {
            _console(console.error, arguments), push(arguments)
        }
    }
}), define("notifications/views", [], function () {
    var NotificationView = Backbone.View.extend({
        incrementCount: function () {
            var count = Number(this.$el.html() || 0);
            this.$el.html(String(count + 1)).show()
        },
        decrementCount: function () {
            var count = Number(this.$el.html() || 0),
                newCount = Math.max(count - 1, 0);
            0 === newCount && this.$el.hide(), this.$el.html(String(newCount))
        }
    });
    return {
        NotificationView: NotificationView
    }
}), define("base/notifications", ["util"], function (util) {
    var MESSAGE_TYPES = {
            INFO: "info",
            SUCCESS: "success",
            WARNING: "warning",
            ERROR: "error"
        },
        FlashMessage = Backbone.Marionette.View.extend({
            template: Backbone.Marionette.TemplateCache.get("#notification-template"),
            events: {
                "click .js-close": "hide"
            },
            initialize: function (options) {
                this.type = _(MESSAGE_TYPES).contains(options.type) ? options.type : MESSAGE_TYPES.SUCCESS, this.timeVisible = options.timeVisible, options.message instanceof $ && (options.message = options.message.html()), this.setElement(this.template({
                    message: options.message
                }).trim(), !0), options.showIcon || this.$el.children(".icon").remove(), options.showClose || this.$el.children(".js-close").remove(), $("body").append(this.$el), this._super = FlashMessage.prototype
            },
            show: function () {
                this.$el.addClass(this.type), FlashMessage.visible.add(this), this.reflow(), this.$el.fadeIn(), this.timeVisible && _.delay(this.hide.bind(this), this.timeVisible)
            },
            hide: function () {
                this.$el.fadeOut(function () {
                    FlashMessage.visible.remove(this)
                }.bind(this))
            },
            getHeight: function () {
                return this.$el.outerHeight()
            },
            reflow: function () {
                this.$el.css("top", FlashMessage.visible.getTop(this))
            }
        });
    FlashMessage.visible = function () {
        var visible = [],
            otherHeight = 0,
            ITEM_MARGIN = 6,
            reflowAll = function () {
                _(visible).each(function (item) {
                    item.reflow()
                })
            };
        return {
            add: function (item) {
                visible.push(item), visible = _(visible).uniq()
            },
            remove: function (item) {
                visible = _(visible).without(item), reflowAll()
            },
            addHeaderHeight: function (height) {
                otherHeight += height, reflowAll()
            },
            getTop: function (item) {
                for (var height = util.topNavHeight + otherHeight, i = 0; i < visible.length; i++) {
                    var message = visible[i];
                    if (item === message) break;
                    height += item.getHeight() + ITEM_MARGIN
                }
                return height + ITEM_MARGIN
            }
        }
    }();
    var TitleRotator = function () {
        this.interval = setInterval(this.rotate.bind(this), 2e3), this.titles = [], this.originalTitle = document.title
    };
    _.extend(TitleRotator.prototype, {
        rotate: function () {
            if (document.title == this.originalTitle) {
                if (0 === this.titles.length) return;
                document.title = _.last(this.titles).getTitle()
            } else document.title = this.originalTitle
        },
        setTitle: function (item) {
            this.removeTitle(item), this.titles.push(item)
        },
        removeTitle: function (item) {
            var index = _.indexOf(this.titles, item); - 1 !== index && this.titles.splice(index, 1)
        }
    });
    var rotator = new TitleRotator,
        createMessage = function (options) {
            options = options || {};
            var extend = options.extend || {};
            return delete options.extend, new(FlashMessage.extend(extend))(options)
        };
    return {
        TYPE: MESSAGE_TYPES,
        FlashMessage: FlashMessage,
        addTabTitle: rotator.setTitle.bind(rotator),
        removeTabTitle: rotator.removeTitle.bind(rotator),
        create: createMessage,
        show: function (options) {
            var message = createMessage(options);
            return message.show(), message
        },
        addHeaderHeight: FlashMessage.visible.addHeaderHeight
    }
}), define("base/connection-status", ["base/notifications", "ack", "events", "rollbar", "config"], function (notifications, ack, events, rollbar, config) {
    return function () {
        var timeoutMessage = notifications.create({
            type: notifications.TYPE.WARNING,
            message: $("#no-connection-message"),
            showClose: !0,
            extend: {
                events: {
                    "click .js-refresh": "refresh"
                },
                refresh: function () {
                    window.location.reload()
                }
            }
        });
        timeoutMessage.$el.addClass("connection-status");
        var slowMessage = notifications.create({
            type: notifications.TYPE.WARNING,
            message: $("#slow-connection-message"),
            showClose: !0
        });
        slowMessage.$el.addClass("connection-status");
        var logEvent = function (state, avg) {
            events.create(events.EVENT.REALTIME_CONNECTION_CHANGED, {
                state: state,
                avg: avg
            }), rollbar.log("realtime_connection_" + state)
        };
        if (config.isAuthenticated && !window.io && (ack.forceTimedOut(), timeoutMessage.show()), ack.onTimeout(function (avg) {
            timeoutMessage.show(), slowMessage.hide(), logEvent("disconnected", avg)
        }), ack.onReconnect(function (avg) {
            timeoutMessage.hide(), logEvent("reconnected", avg)
        }), ack.onSlowConnection(function (avg) {
            logEvent("slow", avg)
        }), ack.onFastConnection(function (avg) {
            logEvent("normal", avg)
        }), config.CHECK_SLOW_CONNECTION) {
            var lastSlowTimeout = 0;
            ack.onSlowConnection(function () {
                var time = new Date;
                time - lastSlowTimeout > 6e5 && (slowMessage.show(), timeoutMessage.hide(), lastSlowTimeout = time)
            }), ack.onFastConnection(slowMessage.hide.bind(slowMessage))
        }
    }
}), define("base/models", ["util", "config", "chat/constants"], function (util, config, constants) {
    ! function () {
        var _sync = Backbone.sync;
        Backbone.sync = function (method, model, options) {
            return options.beforeSend = function (xhr) {
                xhr.setRequestHeader("X-CSRFToken", config.CSRF_TOKEN)
            }, _sync(method, model, options)
        }
    }();
    var AsyncCollection = Backbone.Collection.extend({
            initialize: function () {
                util.makeDeferred(this), this.init.apply(this, arguments)
            },
            init: function () {},
            fetch: function (options) {
                options = options || {};
                var success = options.success || function () {};
                return options.success = function () {
                    success.apply(this, arguments), options.notify ? this.notify() : this.resolve()
                }.bind(this), Backbone.Collection.prototype.fetch.call(this, options)
            }
        }),
        Connection = Backbone.Model.extend({
            urlRoot: "/api/connections/",
            defaults: {
                state: constants.CONNECTION_STATE.NORMAL
            },
            isNormal: function () {
                return this.get("state") == constants.CONNECTION_STATE.NORMAL
            },
            isBlocked: function () {
                return this.get("state") == constants.CONNECTION_STATE.BLOCKED
            },
            isHidden: function () {
                return this.get("state") == constants.CONNECTION_STATE.HIDDEN
            },
            hasLessonScheduled: function () {
                return this.has("lesson_scheduled")
            },
            setNormal: function () {
                return this.set("state", constants.CONNECTION_STATE.NORMAL), this
            },
            setBlocked: function () {
                return this.set("state", constants.CONNECTION_STATE.BLOCKED), this
            },
            setHidden: function () {
                return this.set("state", constants.CONNECTION_STATE.HIDDEN), this
            }
        }),
        Connections = AsyncCollection.extend({
            model: Connection,
            url: "/api/connections/",
            init: function () {
                this.modelData = {}
            },
            getOrCreate: function (opts) {
                var connection, newConnection = !1;
                if (opts.user && opts.otherUser && opts.user in this.modelData && opts.otherUser in this.modelData[opts.user]) {
                    var data = this.modelData[opts.user][opts.otherUser];
                    connection = new Connection(_.extend(opts, data)), newConnection = !0, delete this.modelData[opts.user][opts.otherUser], _.keys(this.modelData[opts.user]).length || delete this.modelData[opts.user]
                } else connection = this.findWhere(opts), connection || (connection = new Connection(opts), newConnection = !0);
                return newConnection && this.add(connection), connection
            },
            set: function (models, options) {
                return options = options || {}, options.fetch ? (this.modelData = {}, _.each(models, function (modelData) {
                    this.modelData[modelData.user] || (this.modelData[modelData.user] = {}), this.modelData[modelData.user][modelData.otherUser] = {
                        id: modelData.id,
                        state: modelData.state,
                        lessonLatestSubject: modelData.lesson_latest_subject,
                        lessonLatestTime: modelData.lesson_latest_time
                    }
                }.bind(this)), void 0) : Backbone.Collection.prototype.set.apply(this, arguments)
            }
        }),
        User = Backbone.Model.extend({
            urlRoot: "/api/users/"
        }),
        Users = AsyncCollection.extend({
            model: User,
            url: "/api/users/"
        }),
        CollectionManager = function () {
            this.constructors = {
                connections: Connections
            }, this.collections = {}
        };
    _.extend(CollectionManager.prototype, {
        getCollection: function (name) {
            if (!this.collections[name]) {
                var collection = new this.constructors[name];
                collection.fetch(), this.collections[name] = collection
            }
            return this.collections[name]
        }
    });
    var Manager = new CollectionManager;
    return {
        AsyncCollection: AsyncCollection,
        Connection: Connection,
        Connections: Connections,
        User: User,
        Users: Users,
        Manager: Manager
    }
}), define("base/constants", function () {
    var ROLE = {
            STUDENT: 1,
            TUTOR: 2,
            PARENT: 3
        },
        SHARE_CONTEXT = {
            LESSON: 1,
            Q_AND_A: 2,
            EXPLANATION: 3,
            GIFT: 4
        },
        RECURRING_TYPE = {
            DAILY: 1,
            WEEKLY: 2
        },
        CONNECTION_STATE = {
            BLOCKED: -2,
            HIDDEN: -1,
            NORMAL: 1
        };
    return {
        CONNECTION_STATE: CONNECTION_STATE,
        RECURRING_TYPE: RECURRING_TYPE,
        ROLE: ROLE,
        ROLE_STR: _.invert(ROLE),
        SHARE_CONTEXT: SHARE_CONTEXT,
        SHARE_CONTEXT_STR: _.invert(SHARE_CONTEXT)
    }
}), define("base/views", ["base/constants", "base/notifications", "subjects/search", "config", "util", "events"], function (constants, notifications, search, config, util, events) {
    var loggedOutHeader, signupForm, dialogs = [],
        DialogCover = Backbone.View.extend({
            $cover: $("<div/>").addClass("cover").appendTo($("body")),
            initialize: function (options) {
                this.header = options.header;
                var topNavHeight = util.topNavHeight,
                    h = $(document).height() - topNavHeight - 1;
                this.$cover.css({
                    top: topNavHeight + "px",
                    height: h + "px"
                }), dialogs.push(this.$el)
            },
            showCover: function ($el) {
                if (this.$cover.css("opacity", .55).on("click", this.hideCover.bind(this)), _.each(dialogs, function ($dialog) {
                    $dialog.hide()
                }), $el) {
                    var width = $el.outerWidth(),
                        left = $el.offset().left,
                        right = $(window).width() - (left + width);
                    this.$el.css({
                        right: right + Math.floor(width / 2) - Math.floor(this.$el.outerWidth() / 2) + "px"
                    })
                }
                this.$cover.show()
            },
            hideCover: function () {
                return this.$el.hide(), this.$cover.hide(), !1
            },
            showPopover: function ($el) {
                if (this.$cover.on("click", this.hidePopover.bind(this)), _.each(dialogs, function ($dialog) {
                    $dialog.hide()
                }), $el) {
                    var width = $el.outerWidth(),
                        left = $el.offset().left,
                        right = $("#header-right-container").width() - (left + width);
                    this.$el.css({
                        right: right + Math.floor(width / 2) - Math.floor(this.$el.outerWidth() / 2) + "px"
                    })
                }
                this.$cover.css("opacity", 0).show()
            },
            hidePopover: function () {
                return this.header.hideForm(), this.$el.hide(), this.$cover.hide(), !1
            }
        }),
        SignInHeaderForm = DialogCover.extend({
            endpoint: "registration/custom-login/",
            events: {
                "submit .sign-in-form-js": "submit",
                "click .sign-in-form-js .sign-in-submit": "submit",
                "click .sign-in-form-js .btn-primary": "submit"
            },
            initialize: function () {
                DialogCover.prototype.initialize.apply(this, arguments), this.$form = this.$("form"), this.$button = this.$(".sign-in-submit")
            },
            show: function ($el) {
                this.showPopover($el), this.$el.show(), this.$button.button("reset")
            },
            submit: function (event) {
                return this.$button.button("loading"), util.API.formSubmit(this.$form, event, {
                    endpoint: this.endpoint,
                    data: this.getSubmitData(),
                    redirects: !0,
                    ajaxOptions: {
                        success: this.submitSuccess.bind(this),
                        error: function (data, xhr) {
                            return 400 != xhr.status ? (window.showErrorCatchall(), void 0) : (this.$button.css("marginTop", "0").button("reset"), $(".facebook-sign-in-error:visible") ? this.$(".facebook-sign-in-error").fadeOut("100", function () {
                                this.$(".sign-in-form-error").slideDown("200").fadeIn()
                            }.bind(this)) : this.$(".sign-in-form-error").slideDown("200").fadeIn(), void 0)
                        }.bind(this)
                    }
                }), !1
            },
            getSubmitData: function () {
                var loginData = this.$form.serialize(),
                    path = document.location.pathname;
                return loginData = loginData.length > 0 ? loginData + "&path=" + path : "path=" + path
            },
            submitSuccess: function (data) {
                var nextURL = window.getNextURL(),
                    url = window.BASE_URL;
                nextURL ? url = nextURL : data.nextURL && (url = data.nextURL), window.location.href = url
            }
        }),
        SignUpHeaderForm = DialogCover.extend({
            events: {
                "click #create-account": "submit",
                keypress: "enterSubmit"
            },
            initialize: function () {
                DialogCover.prototype.initialize.apply(this, arguments), this.$form = this.$("#sign-up-form"), this.$button = this.$("#create-account")
            },
            enterSubmit: function (event) {
                util.isEnterKey(event) && this.submit(event)
            },
            submit: function (event) {
                var data = this.getData(),
                    $errors = $(".email-form-error, .email-invalid-form-error, .required-form-error, .password-form-error"),
                    elem = this;
                return util.API.formSubmit(elem.$form, event, {
                    endpoint: "registration/header-signup/",
                    data: data,
                    $btn: this.$button,
                    redirects: !0,
                    ajaxOptions: {
                        start: function () {
                            elem.$button.button("loading")
                        },
                        checkDataForDoubleSubmit: !0,
                        success: function (data) {
                            $errors.hide(), elem.submitSuccess(data)
                        },
                        error: function (data) {
                            elem.$button.button("reset"), $errors.hide(), data.errors && ("This email is already taken." == data.errors.email ? elem.$(".email-form-error").show() : "Enter a valid email address." == data.errors.email && elem.$(".email-invalid-form-error").show(), data.errors.password && "This field is required." != data.errors.password && elem.$(".password-form-error").text(data.errors.password).show(), $errors.filter(":visible").exists() || _.each(data.errors, function (error) {
                                "This field is required." == error && elem.$(".required-form-error").show()
                            }))
                        }
                    }
                }), !1
            },
            getData: function () {
                return this.$form.serialize()
            },
            submitSuccess: function (data) {
                window.location.href = data.nextURL
            }
        }),
        HeaderSearchForm = search.SubjectSearchView.extend({
            events: {
                "focus input": "focused",
                "blur input": "blurred"
            },
            focused: function () {
                this.$el.addClass("infocus"), this.$("#header-search").mouseup(function () {
                    return !1
                }).select()
            },
            blurred: function () {
                this.$el.removeClass("infocus")
            },
            startSubmit: function () {
                search.SubjectSearchView.prototype.startSubmit.call(this), this.$el.addClass("searching")
            },
            finishSubmit: function () {
                search.SubjectSearchView.prototype.finishSubmit.call(this), this.$el.removeClass("searching")
            }
        }),
        LoggedOutHeaderView = Backbone.Marionette.View.extend({
            ui: {
                navBtn: ".nav-btn",
                headerForm: ".header-form",
                signIn: "#sign-in"
            },
            events: {
                "click [data-toggle=modal]": "modalClicked",
                "click #sign-in": "toggleSignIn",
                "click #how-it-works": "toggleHowItWorks"
            },
            initialize: function () {
                this.bindUIElements(), this.signupForm = new SignUpHeaderForm({
                    el: $("#signup-container"),
                    header: this
                }), this.signinForm = new SignInHeaderForm({
                    el: $("#sign-in-form-dropdown"),
                    header: this
                }), this.$howitworks = $("#howitworks-panel"), this.$howitworks.find(".close-panel").on("click", this.toggleHowItWorks.bind(this))
            },
            hideForm: function () {
                this.ui.navBtn.removeClass("open"), this.ui.headerForm.find(".form-errors").hide()
            },
            modalClicked: function () {
                this.hideSignIn()
            },
            showSignIn: function () {
                this.ui.signIn.addClass("open"), this.signinForm.show(this.ui.signIn), util.focusAndHighlight($("#id-header-login-email"))
            },
            hideSignIn: function () {
                this.hideForm(), this.signinForm.hidePopover()
            },
            toggleSignIn: function (event) {
                var $signinBtn = $(event.target);
                return $signinBtn.hasClass("open") ? this.hideSignIn() : (Backbone.trigger("omnibar:minimizeIfNotDocked"), this.showSignIn()), !1
            },
            toggleHowItWorks: function () {
                var $hiw = this.$howitworks,
                    $html = $("html, body"),
                    isPanelOpen = $hiw.hasClass("panel-open"),
                    atTopOfWindow = 0 === $(window).scrollTop();
                return atTopOfWindow ? isPanelOpen ? $hiw.slideUp(500).removeClass("panel-open") : $hiw.slideDown(500).addClass("panel-open") : isPanelOpen ? $html.animate({
                    scrollTop: "0px"
                }) : $html.animate({
                    scrollTop: "0px"
                }, {
                    complete: function () {
                        $hiw.slideDown(500).addClass("panel-open")
                    }
                }), !1
            }
        }),
        LoggedInHeaderView = LoggedOutHeaderView.extend({
            ui: {
                navBtn: ".nav-btn"
            },
            events: {
                "click #how-it-works": "toggleHowItWorks",
                "click #account-btn": "minimizeOmnibarIfNotDocked"
            },
            minimizeOmnibarIfNotDocked: function () {
                $("#account-btn-container li").hasClass("open") || Backbone.trigger("omnibar:minimizeIfNotDocked")
            },
            initialize: function () {
                this.bindUIElements(), this.$howitworks = $("#howitworks-panel"), this.$howitworks.find(".close-panel").on("click", this.toggleHowItWorks.bind(this))
            }
        }),
        SignUpModal = function (className, options) {
            var $modal = $(".signup-webform-modal"),
                $carrot = $modal.find("." + className),
                _submitSuccess = signupForm.submitSuccess,
                callingArgs = [],
                updateArgs = function (_arguments) {
                    var args = Array.prototype.slice.apply(_arguments);
                    return args.push($modal), args.push($carrot), args
                },
                onHide = function () {
                    $modal.removeClass("show-carrot"), $carrot.hide(), options.onHide && options.onHide.apply(options.onHide, updateArgs(callingArgs)), options.onSuccess && (signupForm.submitSuccess = _submitSuccess), $modal.off("hidden", onHide)
                };
            return {
                show: function () {
                    $carrot.show(), $modal.addClass("show-carrot").modal("show").on("hidden", onHide);
                    var args = updateArgs(arguments);
                    callingArgs = arguments, options.onShow && options.onShow.apply(options.onShow, args), options.onSuccess && (signupForm.submitSuccess = function (data) {
                        args.unshift(data), options.onSuccess.apply(options.onSuccess, args)
                    })
                },
                hide: onHide
            }
        };
    return {
        SignUpModal: SignUpModal,
        SignUpForm: SignUpHeaderForm,
        SignInForm: SignInHeaderForm,
        getLoggedOutHeader: function () {
            return loggedOutHeader
        },
        setupUpcomingLesson: function () {
            var $timer = $("#upcoming-lesson-timer");
            $timer.exists() && (new util.DiffTimerView({
                el: $timer,
                useDelimiter: !0,
                showSeconds: !0,
                showHours: !1
            }), notifications.addHeaderHeight($("#upcoming-lesson-banner").outerHeight()))
        },
        setupHeader: function () {
            config.isAuthenticated ? new LoggedInHeaderView({
                el: $("#header")
            }) : (loggedOutHeader = new LoggedOutHeaderView({
                el: $("#header")
            }), signupForm = loggedOutHeader.signupForm, "/accounts/login/" == location.pathname && new SignInHeaderForm({
                el: $("#login-required-sign-in-form").parent()
            }), $(".signup-webform-modal").on("show", function () {
                events.create(events.EVENT.REGISTRATION_SIGNUP_MODAL_OPENED)
            })), config.isAuthenticated && config.role == constants.ROLE.TUTOR ? require(["experts/availability"], function (avail) {
                new avail.AvailableNow({
                    el: "#available-now-dropdown"
                })
            }) : new HeaderSearchForm({
                el: "#header-search-container"
            })
        }
    }
}), define("inbox/views", ["chat/view-utils", "util", "config"], function (viewUtils, util, config) {
    var modal, inbox, InboxView = Backbone.View.extend({
            $messages: null,
            formView: null,
            events: {
                "click li.message": "showConversation",
                "click #new-message": "showModal",
                "click #load-more a": "loadMore",
                "click .js-blast-message-modal": "showBlastMessageModal"
            },
            initialize: function (opts) {
                this.$messages = this.$("ul#messages"), this.$loadLink = this.$("div#load-more"), this.moreToLoad = opts.moreToLoad, this.startID = opts.startID, this.loadMoreURL = opts.loadMoreURL, this.forwardsState = opts.forwardsState, this.backwardsState = opts.backwardsState, this.messageHtmlURL = config.MESSAGE_HTML_URL, this.loadLimit = 20, this.loadingMore = !1, this.$(".message p").linkify(), this.renderAction(this.$el)
            },
            renderAction: function ($el) {
                $el.find("[data-action]").each(function (idx, el) {
                    var $el = $(el),
                        html = viewUtils.getMessageActionHTML($el.data("action"));
                    html && $el.append(html)
                })
            },
            loadMore: function () {
                return this.loadingMore ? !1 : (this.loadingMore = !0, $.ajax({
                    url: this.loadMoreURL,
                    data: {
                        beforeID: this.startID,
                        limit: this.loadLimit
                    },
                    cache: !1,
                    success: this.loadMoreSuccess.bind(this),
                    error: function () {
                        this.loadingMore = !1
                    }.bind(this)
                }), !1)
            },
            loadMoreSuccess: function (data) {
                this.loadingMore = !1, this.moreToLoad = data.more, this.startID = data.startID, this.$messages.append(this.linkify(data.html)), this.moreToLoad || this.$loadLink.hide()
            },
            linkify: function (html) {
                var $html = $(_.trim(html));
                return $html.closest(".message").find("p").linkify(), $html
            },
            showConversation: function (event) {
                event.preventDefault();
                var $li = $(event.target).closest("li.message");
                document.location.href = $li.attr("data-url")
            },
            showModal: function (event) {
                event.preventDefault(), modal.modal("show"), $("#id_recipient").chosen(), this.formView = new NewMessageView({
                    el: modal
                })
            },
            addMessage: function ($html) {
                this.$messages.find("li#no-messages").hide(), this.renderAction($html), this.$messages.prepend($html)
            },
            addReply: function ($html) {
                return this.$messages.find("li#no-messages").hide(), this.renderAction($html), this.$messages.append($html), $html
            },
            getMessageHTML: function (messageID, callback) {
                callback = callback || function () {}, $.ajax({
                    url: this.messageHtmlURL,
                    type: "GET",
                    data: {
                        id: messageID
                    },
                    dataType: "json",
                    cache: !1,
                    success: _.bind(callback, this)
                })
            },
            renderMessage: function (attrs) {
                this.getMessageHTML(attrs.id, _.bind(function (data) {
                    this.addMessage(this.linkify(data.html).hide())
                }, this))
            },
            showHiddenMessages: function () {
                this.$el.find("li.message:hidden").show()
            },
            getMessages: function () {
                return this.$el.find("li.message")
            },
            removeDuplicateConversations: function () {
                var parentID, $msg, conversations = {};
                _.each(this.getMessages(), function (msg) {
                    $msg = $(msg), parentID = $msg.attr("data-parentid"), _.isUndefined(conversations[parentID]) ? conversations[parentID] = !0 : $msg.remove()
                })
            },
            showBlastMessageModal: function () {
                return viewUtils.blastMessageModal.show(), !1
            }
        }),
        ConversationView = InboxView.extend({
            renderMessage: function (attrs, showAlertCallback) {
                this.getMessageHTML(attrs.id, _.bind(function (data) {
                    data.parentID === attrs.parentID ? (this.addMessage(data.html).hide(), showAlertCallback(!0)) : showAlertCallback(!1)
                }, this))
            },
            showConversation: function () {},
            removeDuplicateConversations: function () {},
            showHiddenMessages: function () {
                this.$el.find("li.message:hidden").show()
            },
            addMessage: function (html) {
                return this.addReply(this.linkify(html).removeClass("unread"))
            },
            loadMoreSuccess: function (data) {
                this.loadingMore = !1, this.moreToLoad = data.more, this.startID = data.startID, this.$messages.prepend(this.linkify(data.html)), this.moreToLoad || this.$loadLink.hide()
            }
        }),
        NewMessageView = Backbone.View.extend({
            $send: null,
            $form: null,
            events: {
                "click #send": "sendMessage",
                "submit form": "sendMessage"
            },
            initialize: function (options) {
                this.$send = $("#send"), this.$form = $("#message-form"), this.$send.tooltip({
                    trigger: "hover"
                }), this.$attachment = this.$form.find("[name=attachment]"), this.$textarea = this.$form.find("textarea"), this.otherUniqueID = options.otherUniqueID;
                var self = this;
                util.fileUpload(this.$form, {
                    url: this.getUploadURL(),
                    beforeAdd: function () {
                        self.fileUploading = !0, self.$send.addClass("disabled").prop("disabled", !0)
                    },
                    done: function (e, data) {
                        self.$attachment.val(data.result.id)
                    },
                    beforeFail: function (e, data) {
                        data.jqXHR.status >= 400 && data.jqXHR.status < 500 && self.$attachment.val("")
                    },
                    afterAlways: function () {
                        self.fileUploading = !1, self.$send.removeClass("disabled").prop("disabled", !1)
                    }
                })
            },
            getUploadURL: function () {
                return config.BASE_URL + "inbox/attachment/"
            },
            enabled: function () {
                return !this.$send.hasClass("disabled")
            },
            sendMessage: function (event) {
                return event.preventDefault(), this.$send.tooltip("hide"), this.fileUploading ? !1 : !this.enabled() || "" === this.$textarea.val() && "" === this.$attachment.val() ? !1 : (this.$send.addClass("disabled").prop("disabled", !0), util.API.formSubmit(this.$form, event, {
                    endpoint: config.MESSAGE_POST_URL,
                    ajaxOptions: {
                        checkDataForDoubleSubmit: !0,
                        success: _.bind(this.success, this),
                        complete: function () {
                            this.$send.removeClass("disabled").prop("disabled", !1)
                        }.bind(this)
                    }
                }), void 0)
            },
            success: function (data) {
                inbox.addMessage(data.html), inbox.removeDuplicateConversations(), this.$form.hide();
                var $send = this.$send,
                    $form = this.$form,
                    $alert = modal.find(".alert");
                $alert.show(), modal.on("hidden", function () {
                    $send.removeClass("disabled"), $alert.hide(), $form[0].reset(), $form.show().find(".errorlist").hide()
                }), _.delay(function () {
                    modal.modal("hide")
                }, 1500)
            }
        }),
        NewMessageAlertView = Backbone.View.extend({
            inbox: null,
            count: 0,
            events: {
                click: "clickHandler"
            },
            initialize: function (args) {
                this.inbox = args.inbox
            },
            render: function () {
                return this.$el.html(_.sprintf("You have %s new message%s. Click to show.", String(this.count), 1 === Number(this.count) ? "" : "s")), this
            },
            show: function () {
                return this.$el.slideDown(), this
            },
            hide: function () {
                return this.$el.hide(), this
            },
            incrementCount: function () {
                return ++this.count, this
            },
            resetCount: function () {
                return this.count = 0, this
            },
            clickHandler: function () {
                this.hide().resetCount(), this.inbox.showHiddenMessages(), this.inbox.removeDuplicateConversations()
            }
        });
    return {
        InboxView: InboxView,
        ConversationView: ConversationView,
        NewMessageView: NewMessageView,
        NewMessageAlertView: NewMessageAlertView,
        setupInbox: function (opts) {
            modal = $("#form-modal"), modal.length > 0 && modal.modal({
                keyboard: !1,
                show: !1
            });
            var View = opts.view || InboxView;
            return inbox = new View({
                el: $("#messages-container"),
                moreToLoad: opts.moreToLoad,
                startID: opts.startID,
                loadMoreURL: opts.loadMoreURL,
                forwardsState: opts.forwardsState,
                backwardsState: opts.backwardsState
            })
        }
    }
}), define("chat/phrasebank", ["events", "util"], function (events, util) {
    var activeView = null,
        _closePhrasebank = function (view, phrasebankView) {
            $(document).off("keydown.phrasebank"), $(document).off("click.phrasebank"), phrasebankView.hide(view), activeView.stopListening(phrasebankView, "phraseClicked"), activeView = null
        },
        PhraseView = Backbone.Marionette.ItemView.extend({
            template: "#phrase-template",
            tagName: "div",
            className: "phrase close-popover",
            events: {
                click: "phraseClicked"
            },
            phraseClicked: function (event) {
                this.trigger("phraseClicked", this.model, event)
            }
        }),
        PhrasebankView = Backbone.Marionette.CompositeView.extend({
            template: "#phrasebank-template",
            itemViewContainer: ".phrases",
            itemView: PhraseView,
            ui: {
                phrases: ".phrases"
            },
            itemEvents: {
                phraseClicked: function (eventName, view, model, event) {
                    this.trigger("phraseClicked", model, event.type)
                }
            },
            initialize: function () {
                this.container = $("#phrasebank")
            },
            listenForKeydown: function () {
                $(document).one("keydown.phrasebank", function (event) {
                    if (event.preventDefault(), event.keyCode === util.Event.KEY_ESCAPE) return _closePhrasebank(activeView, this), void 0;
                    var phraseModel = this.collection.findWhere({
                        id: Number(String.fromCharCode(event.keyCode))
                    });
                    return phraseModel ? (this.trigger("phraseClicked", this.collection.findWhere({
                        id: Number(String.fromCharCode(event.keyCode))
                    }), event.type), _closePhrasebank(activeView, this), void 0) : (this.listenForKeydown(), void 0)
                }.bind(this))
            },
            onRender: function () {
                this.container.append(this.$el)
            },
            show: function ($attachedTo, affix) {
                this.ui.phrases.scrollTop(0);
                var offset = $attachedTo.offset();
                this.container.toggleClass("inline", !affix), this.container.fadeIn(200).offset({
                    left: offset.left - this.container.width() + 40,
                    top: offset.top - this.container.height() - 10
                }), this.listenForKeydown()
            },
            hide: function (view) {
                activeView && activeView === view && this.container.fadeOut(100)
            }
        }),
        Phrase = Backbone.Model.extend({
            defaults: {
                title: "",
                body: ""
            }
        }),
        Phrasebank = Backbone.Collection.extend({
            model: Phrase,
            initialize: function () {
                var phraseMarkup = _.trim($("#phrasebank-phrases").html()),
                    $phrases = $(phraseMarkup).find(".phrase");
                $phrases.each(function (i, phrase) {
                    var $phrase = $(phrase);
                    this.add({
                        title: this._getPhraseText($phrase, ".title"),
                        body: this._getPhraseText($phrase, ".body"),
                        id: $phrase.data("id")
                    })
                }.bind(this))
            },
            _getPhraseText: function ($phrase, selector) {
                var text = $phrase.find(selector).text();
                return _.trim(_.clean(text))
            }
        }),
        PhrasebankManager = function () {
            var view = null,
                getView = function () {
                    return view || (view = new PhrasebankView({
                        collection: new Phrasebank
                    }), view.render(), Backbone.on("phrasebank:close", function () {
                        activeView && _closePhrasebank(activeView, view)
                    })), view
                },
                setupViewListener = function (view, userCode, phraseClickCallback) {
                    var phrasebankView = getView();
                    view.listenTo(phrasebankView, "phraseClicked", function (model, trigger) {
                        events.create(events.EVENT.PHRASEBANK_CLICK_PHRASE, {
                            otherUserUniqueCode: userCode,
                            phraseID: model.id,
                            trigger: trigger
                        }), phraseClickCallback(model.get("body"))
                    })
                },
                setupPhrasebankClickout = function (view) {
                    var phrasebankView = getView();
                    setTimeout(function () {
                        util.triggerOnGlobalClick(function ($target) {
                            return $target.hasClass("close-popover") || $target.parent().hasClass("close-popover") ? !1 : $target.closest(phrasebankView.$el).exists()
                        }, function () {
                            activeView && activeView === view && _closePhrasebank(activeView, phrasebankView)
                        }, {
                            namespace: "phrasebank"
                        })
                    }, 0)
                };
            this.show = function (view, $phrasebankOpenButton, userCode, phraseClickCallback, trigger, options) {
                options = options || {};
                var phrasebankView = getView();
                if (activeView) {
                    if (activeView === view) return;
                    _closePhrasebank(view, phrasebankView)
                }
                activeView = view, events.create(events.EVENT.PHRASEBANK_OPEN, {
                    trigger: trigger,
                    otherUserUniqueCode: userCode
                }), phrasebankView.show($phrasebankOpenButton, options.affix), setupViewListener(view, userCode, phraseClickCallback), setupPhrasebankClickout(view, $phrasebankOpenButton)
            }
        };
    return (new PhrasebankManager).show
}), define("chat/config", ["util"], function (util) {
    var storeKey = "chatConfig",
        config = {
            soundsEnabled: null,
            omnibarMaximized: null
        },
        ChatConfig = function () {
            util.makeDeferred(this);
            var self = this;
            window.asyncStorage.getItem(storeKey, function (chatConfig) {
                _(chatConfig).each(function (v, k) {
                    k in config && (config[k] = v)
                }), self.resolve()
            })
        };
    return _(ChatConfig.prototype).extend({
        updateConfig: function (prop, value) {
            _.isUndefined(value) || config[prop] === value || this.done(function () {
                config[prop] = value, window.asyncStorage.setItem(storeKey, config)
            })
        },
        omnibarMaximized: function (maximize) {
            return this.updateConfig("omnibarMaximized", maximize), _.isUndefined(maximize) ? config.omnibarMaximized : maximize
        },
        soundsEnabled: function (enabled) {
            return this.updateConfig("soundsEnabled", enabled), _.isUndefined(enabled) ? config.soundsEnabled : enabled
        },
        updateChatSounds: function (enabled, errorCallback) {
            util.API.post("/chat/toggle-sounds/", {
                csrf: !0,
                data: {
                    value: enabled
                },
                success: function () {
                    this.soundsEnabled(enabled)
                }.bind(this),
                error: errorCallback
            })
        }
    }), new ChatConfig
}), define("chat/view-utils", ["chat/constants", "experts/messages", "events"], function (constants, messages, events) {
    var getGenderPronouns = function (gender) {
            var genderPronouns = {
                subjective: "they",
                objective: "their",
                plural: ""
            };
            return "M" == gender ? genderPronouns = {
                subjective: "he",
                objective: "him",
                plural: "s"
            } : "F" == gender && (genderPronouns = {
                subjective: "she",
                objective: "her",
                plural: "s"
            }), genderPronouns
        },
        getIndicatorClass = function (user) {
            var indicatorClass = constants.INDICATOR_CLASS.ONLINE;
            return user.isOffline() ? indicatorClass = constants.INDICATOR_CLASS.OFFLINE : user.isAvailableNow() ? indicatorClass = constants.INDICATOR_CLASS.AVAILABLE_NOW : user.isBusy() ? indicatorClass = constants.INDICATOR_CLASS.BUSY : user.isAway() && (indicatorClass = constants.INDICATOR_CLASS.AWAY), indicatorClass
        },
        getIndicatorTitle = function (user) {
            var title = getIndicatorClass(user);
            return title = title == constants.INDICATOR_CLASS.AVAILABLE_NOW ? "Ready to teach now!" : _.ucfirst(title)
        },
        getUserJSON = function (model) {
            var user = model.toJSON(),
                firstName = user.name.split(" ", 1);
            return user = _.chain(user).defaults(model.defaults).extend({
                indicatorClass: getIndicatorClass(model),
                indicatorTitle: getIndicatorTitle(model),
                roleStr: _.ucfirst(user.role ? constants.ROLE_STR[user.role] : constants.ROLE_STR[1]),
                isParent: model.isParent(),
                isTutor: model.isTutor(),
                isStudent: model.isStudent(),
                isSubjectSection: model.isSubjectSectionUser(),
                firstName: firstName,
                chatName: model.isSuperuser() ? firstName : user.name,
                isAuth: model.isAuthenticated()
            }).value(), user.isSubjectSection && model.isAway() && (user.indicatorClass = "online", user.indicatorTitle = "Online"), model.isTutor() ? (user.headerName = _.rtrim(user.name, "."), user.urlID && (user.headerName = _.sprintf('<a href="/online-tutors/%s/">%s</a>', user.urlID, user.headerName))) : user.headerName = user.chatName, model.isSuperuser() ? user.headerName = _.sprintf("Support: %s", user.headerName) : model.isBot() || (user.headerName = _.sprintf("%s: %s", user.roleStr, user.headerName)), user.genderPronouns = getGenderPronouns(user.gender), user
        },
        HiddenUsers = function () {
            this._users = [], this._timeout = null
        };
    _.extend(HiddenUsers.prototype, {
        REMOVE_DELAY: 2e3,
        add: function (chatUserView) {
            this._users.push(chatUserView), this.setHiddenTimeout()
        },
        remove: function (chatUserView) {
            this._users = _(this._users).without(chatUserView), this.setHiddenTimeout()
        },
        setHiddenTimeout: function () {},
        hideHiddenUsers: function () {
            clearTimeout(this._timeout), _(this._users).each(function (chatUserView) {
                chatUserView.destroy()
            }), this._users = []
        }
    });
    var BlastMessageModal = messages.ModalMessageForm.extend({
            onShow: function () {
                events.create(events.EVENT.SUPPORT_MESSAGE_BLAST_MODAL, {
                    state: "opened"
                })
            },
            onSuccess: function () {
                events.create(events.EVENT.SUPPORT_MESSAGE_BLAST_MODAL, {
                    state: "submitted"
                })
            }
        }),
        indicatorClasses = _.chain(constants.INDICATOR_CLASS).values().map(function (item) {
            return "chat-" + item
        }).value().join(" "),
        getMessageAction = function (action) {
            switch (action) {
            case constants.MESSAGE_ACTION.REENGAGE:
                return {
                    event: "js-blast-message-modal",
                    text: "Submit a message"
                }
            }
            return null
        };
    return {
        getUserJSON: getUserJSON,
        getGenderPronouns: getGenderPronouns,
        getIndicatorClass: getIndicatorClass,
        getIndicatorTitle: getIndicatorTitle,
        HiddenUsers: HiddenUsers,
        indicatorClasses: indicatorClasses,
        getMessageActionHTML: function (action) {
            var actionData = getMessageAction(action);
            return actionData ? _.sprintf('<a class="action %s" href="javascript://">%s</a>', actionData.event, actionData.text) : ""
        },
        getMessageAction: getMessageAction,
        blastMessageModal: new BlastMessageModal({
            el: "#chat-blast-message-form"
        }),
        tutorRequestQuestion: function (tutor, student) {
            var tmpl = Backbone.Marionette.TemplateCache.get("#chat-request-question-template"),
                text = tmpl({
                    id: tutor.id
                });
            Backbone.trigger("chat:open", student, function (chat) {
                chat.pushMessage(text)
            })
        },
        playChatSound: function () {
            document.getElementById("chat-sound").play()
        }
    }
}), define("chat/models", ["base/models", "chat/constants", "chat/models/chats", "chat/models/users", "chat/models/util", "heartbeat", "socket", "events", "util", "config", "rollbar"], function (baseModels, constants, chats, users, chatUtil, heartbeat, socket, events, util, config, rollbar) {
    var CLASSES = {
            Connections: baseModels.Connections,
            ChatUserGroups: users.ChatUserGroups,
            Chats: chats.Chats
        },
        InlineChat = function (user) {
            util.makeDeferred(this), this.connections = new CLASSES.Connections, this.groups = new CLASSES.ChatUserGroups, this.chats = new CLASSES.Chats, this.store = window.asyncStorage, this.cache = users.Cache, this._editMode = !1, this.onProgress(), this.setUser(user), this.user.isAuthenticated() && this.setupAuthedUser();
            var self = this;
            Backbone.on("chat:open", function (userData, callback) {
                self.chats.done(function () {
                    var user = users.Cache.getUser(userData);
                    if (user) {
                        var chat = self.openChat(user);
                        _.isFunction(callback) && callback(chat)
                    }
                })
            })
        };
    return _.extend(InlineChat.prototype, Backbone.Events, {
        onProgress: function () {
            this.progress(function () {
                this.groups.fetch(), this.chats.fetch(), this.connections.fetch({
                    fetch: !0,
                    data: {
                        fields: ["id", "user", "otherUser", "state", "lesson_latest_subject", "lesson_latest_time"].join(",")
                    }
                })
            }.bind(this))
        },
        synchronize: function () {
            return $.when(this.chats.synchronize(), this.groups.synchronize()).done(function () {
                users.Cache.resolve()
            })
        },
        setupAuthedUser: function () {
            this.idleWatcher = new chatUtil.IdleWatcher, Backbone.on("chat:busy", this.setBusyState.bind(this)), Backbone.on("chat:su-message", this.sendSUMessage.bind(this)), this.listenTo(users.Cache, "connections.get", this.getConnections), this.sendStoredMessage()
        },
        sendStoredMessage: function () {
            var self = this;
            this.done(function () {
                self.store.getItem(constants.CHAT_STORE_KEY, function (item) {
                    if (item) {
                        self.store.removeItem(constants.CHAT_STORE_KEY);
                        var user = users.Cache.getUser(item.user);
                        self.openChat(user).pushMessage(item.text)
                    }
                })
            })
        },
        enableEditMode: function () {
            this._editMode = !0
        },
        disableEditMode: function () {
            this._editMode = !1
        },
        isEditMode: function () {
            return this._editMode
        },
        setUser: function (user) {
            this.saveUser(users.Cache.getUser(user)), user.id && this.setupSocket()
        },
        setupSocket: function () {
            var availabilityEvents = {
                "chat:update.availability": this.updateAvailability.bind(this)
            };
            users.Cache.on("add", function (user) {
                socket.subscribe("presence=" + user.id, availabilityEvents)
            });
            var self = this,
                userEvents = {
                    "chat:new.message": this.chats.newMessage.bind(this.chats),
                    "connection:update": this.updateConnection.bind(this),
                    "schedule:new.proposal:self": this.sentProposal.bind(this),
                    signedout: this.signOut.bind(this)
                },
                botEvents = {
                    "chat:ping.lesson": function (data) {
                        self.chats.newBotMessage(data, "New lesson opportunity")
                    },
                    "chat:automated.message": function (data) {
                        self.chats.newBotMessage(data, "InstaEDU Tips")
                    }
                };
            _(userEvents).extend(botEvents), socket.subscribe("user=" + this.user.get("userID"), userEvents)
        },
        sentProposal: function (data) {
            var user = users.Cache.get(data.recipientID);
            user && (user.addToRoleSection(), user.hasExistingChat() || user.setChatID(data.chatID))
        },
        loadChats: function (chats) {
            _.each(chats, function (chatData, id) {
                chatData.id = id, this.chats.add(new chats.Chat(chatData))
            }.bind(this))
        },
        openChat: function (user) {
            var chat;
            if (user.chat) chat = user.chat;
            else {
                var id = user.getChatID();
                chat = id ? this.chats.getChat(id) || new chats.Chat({
                    id: id
                }) : this.chats.getChatByUser(user) || new chats.Chat, user.setChat(chat)
            }
            return this.chats.unshiftChat(chat, function () {
                chat.loadHistory(), chat.trigger("focus")
            }), chat
        },
        updateAvailability: function (data) {
            var user = users.Cache.get(data.user.id);
            user && user.updateAvailability(data.user)
        },
        setBusyState: function (isBusy) {
            this.getUser().updateBusyState(isBusy), heartbeat.setBusy(isBusy)
        },
        getNewUserInfo: function (uid) {
            return this.cache.getUserInfo(uid).done(function (user) {
                user.isOffline() || user.addToRoleSection()
            })
        },
        checkLesson: function () {
            if (config.LESSON) {
                var student = config.LESSON.student,
                    tutor = config.LESSON.tutor,
                    isStudent = student == this.getUser().id,
                    other = isStudent ? tutor : student;
                Backbone.on("lesson.ready", function (options) {
                    other = isStudent ? options.tutor : options.student, this.setupForLesson(other)
                }.bind(this)), other && Backbone.trigger("lesson.ready", config.LESSON)
            }
        },
        setupForLesson: function (userID) {
            var self = this,
                showUserInLesson = function (user) {
                    user.set("showInLesson", !0), self.chats.progress(function () {
                        var chat = self.chats.getChatByUser(userID);
                        chat && chat.closeInitial(!0)
                    })
                };
            this.groups.progress(function () {
                var user = users.Cache.getUser(userID);
                user ? showUserInLesson(user) : self.getNewUserInfo(userID).done(showUserInLesson)
            })
        },
        getConnections: function (userID, options, callback) {
            this.connections.done(function () {
                var currentUserID = this.getUser().id;
                options = options || {}, options.forwards || (options.forwards = {
                    user: currentUserID,
                    otherUser: userID
                }), options.backwards || (options.backwards = {
                    user: userID,
                    otherUser: currentUserID
                });
                var forwards = this.connections.getOrCreate(options.forwards),
                    backwards = this.connections.getOrCreate(options.backwards);
                callback(forwards, backwards)
            }.bind(this))
        },
        updateConnection: function (data) {
            var conn = this.connections.findWhere({
                id: data.connection.id
            });
            if (conn) conn.set("state", data.connection.state);
            else {
                var connection = new baseModels.Connection(data.connection);
                this.connections.add(connection)
            }
        },
        getUser: function () {
            return this.user
        },
        saveUser: function (user) {
            users.Cache.currentUser = this.user = user;
            var differentUser = function () {
                    this.deleteData(), rollbar.log("Found different chat user.")
                }.bind(this),
                foundUser = !1;
            this.store.getItemsWithKeysLike("ChatUser\\d+", function (items) {
                _.each(items, function (match) {
                    if (match) {
                        if (match.id != user.id) return differentUser();
                        foundUser = !0
                    }
                }.bind(this)), foundUser || this.deleteData(), this.store.setItem(this.getUserKey(), user.toJSON(), 36e5), this.notify()
            }.bind(this))
        },
        getUserKey: function () {
            return "ChatUser" + this.user.id
        },
        deleteData: function () {
            this.groups.reset(), this.chats.reset(), this.chats.queue.reset(), this.groups.asyncStorage._clear(), this.chats.asyncStorage._clear(), this.chats.queue.asyncStorage._clear(), this.store.removeItemsWithKeysLike("ChatUser\\d+"), window.amplify.store.removeMatching(/ChatUser\d+/), this.store.removeItemsWithKeysLike("^Chat"), window.amplify.store.removeMatching(/^Chat/)
        },
        signOut: function (emit) {
            emit && socket.emit("signout"), socket.disconnect(), this.deleteData(), window.amplify.store("user.signedout", !0), Backbone.trigger("chat.signout", this)
        },
        deferMessage: function (chat, onSave) {
            var text = chat.getStoredText();
            _.isBlank(text) || this.store.setItem(constants.CHAT_STORE_KEY, {
                text: text,
                user: chat.user.toJSON()
            }, 36e5, onSave)
        },
        sendSUMessage: function (messageContext, eventContext) {
            var self = this;
            this.done(function () {
                var suGroup = users.ChatUserGroups.getTypeGroup("su"),
                    su = suGroup.users.first();
                su && !su.isOffline() && util.API.post(chatUtil.getURL("chat/su-message/"), {
                    csrf: !0,
                    data: {
                        context: messageContext
                    },
                    success: function () {
                        var interval = setInterval(function () {
                            if (su.chat) {
                                clearInterval(interval);
                                var chat = self.openChat(su);
                                chat.trigger("maximize")
                            }
                        }, 1e3);
                        events.create(events.EVENT.SUPPORT_AUTOMATED_MESSAGE, {
                            messageContext: messageContext,
                            context: eventContext
                        })
                    }
                })
            })
        }
    }), {
        Message: chats.Message,
        Messages: chats.Messages,
        Chat: chats.Chat,
        Chats: chats.Chats,
        ChatUser: users.ChatUser,
        ChatUsers: users.ChatUsers,
        ChatUserGroup: users.ChatUserGroup,
        ChatUserGroups: users.ChatUserGroups,
        InlineChat: InlineChat,
        CLASSES: CLASSES
    }
}), define("chat/constants", ["base/constants"], function (constants) {
    var AVAILABILITY = {
            OFFLINE: 1,
            AWAY: 2,
            ONLINE: 3
        },
        INDICATOR_CLASS = {
            OFFLINE: "offline",
            AWAY: "away",
            ONLINE: "online",
            AVAILABLE_NOW: "available-now",
            BUSY: "busy"
        },
        MESSAGE_CONTEXT = {
            SU_PAYWALL: 40,
            SU_REENGAGE: 41
        },
        MESSAGE_ACTION = {
            REENGAGE: 1
        };
    return {
        AVAILABILITY: AVAILABILITY,
        AVAILABILITY_STR: _.invert(AVAILABILITY),
        INDICATOR_CLASS: INDICATOR_CLASS,
        INDICATOR_CLASS_STR: _.invert(INDICATOR_CLASS),
        CHAT_STORE_KEY: "chat.store",
        CONNECTION_STATE: constants.CONNECTION_STATE,
        ROLE: constants.ROLE,
        ROLE_STR: constants.ROLE_STR,
        MESSAGE_CONTEXT: MESSAGE_CONTEXT,
        MESSAGE_ACTION: MESSAGE_ACTION
    }
}), define("chat/views", ["base/views", "base/models", "base/notifications", "experts/messages", "schedule/views", "schedule/meet-now", "chat/config", "chat/constants", "chat/models", "chat/view-utils", "chat/phrasebank", "events", "socket", "util", "config"], function (baseViews, baseModels, notifications, messages, schedule, meetNow, chatConfig, constants, models, viewUtils, phrasebank, events, socket, util, config) {
    var inlineChat, omnibar, $blockUserLessonsModal, signUpModal, hiddenUsers = new viewUtils.HiddenUsers,
        BotItem = Backbone.Marionette.ItemView.extend({
            template: "#chat-bot-template",
            messageTemplate: "#chat-message-template",
            tagName: "li",
            ui: {
                body: ".chat-body",
                conversation: ".chat-conversation",
                messages: ".chat-messages",
                minimize: ".chat-minimize i",
                textarea: "textarea"
            },
            events: {
                click: "markAsRead",
                "click .chat-close": "end",
                "click .chat-name a": "clickName",
                "click .chat-header": "toggle",
                "click .js-blast-message-modal": "showBlastMessageModal"
            },
            modelEvents: {
                "remove destroy": "close",
                "messages:add": "append",
                "messages:refresh": "resetConversation",
                "messages:show.timestamp": "showTimestamp",
                "counter.update": "updateCounter",
                close: "removeCounter",
                maximize: "maximize"
            },
            initialize: function () {
                this._messageTemplate = Backbone.Marionette.TemplateCache.get(this.messageTemplate)
            },
            onRender: function () {
                this.setElement(this.$el.children().first()), this.updateCounter()
            },
            onInsertedIntoDom: function () {
                this.initScrolling(), this.closeInitial()
            },
            initScrolling: function () {
                util.scrollLock(this.ui.conversation), this.scrollConversation()
            },
            scrollConversation: function () {
                this.ui.conversation.scrollTop(this.ui.conversation.prop("scrollHeight"))
            },
            closeInitial: function () {
                this.model.closeInitial() && (this.model.closeInitial(null), this.end()), !config.OMNIBAR_SU_ONLY || this.model.user.isSuperuser() || this.model.user.showInLesson() || this.$el.hide(), config.omnibarMinimized && this.minimize()
            },
            end: function () {
                var isFocused = this.isFocused();
                return Backbone.trigger("phrasebank:close"), this.close(), this.removeCounter(), this.markAsRead(), this.model.close(isFocused), !1
            },
            preventToggle: function (event) {
                event.stopPropagation()
            },
            clickName: function (event) {
                this.isMinimized() ? event.preventDefault() : this.preventToggle(event)
            },
            isFocused: function () {
                return this.ui.textarea.is(":focus")
            },
            isExpanded: function () {
                return this.$el.hasClass("expanded")
            },
            isMinimized: function () {
                return !this.isExpanded()
            },
            toggle: function () {
                this.isExpanded() ? this.minimize() : this.maximize()
            },
            minimize: function () {
                this.$el.removeClass("expanded"), this.model.set({
                    minimized: !0
                }), this.removeCounter(), this.ui.minimize.removeClass("minimize-chatlist-icon").addClass("maximize-chatlist-icon"), this.trigger("toggled")
            },
            maximize: function () {
                this.$el.addClass("expanded"), this.model.set({
                    minimized: !1
                }), this.removeCounter(), this.ui.minimize.removeClass("maximize-chatlist-icon").addClass("minimize-chatlist-icon"), this.ui.textarea.focus(), this.scrollConversation(), this.trigger("toggled")
            },
            markAsRead: function () {
                this.model.markAsRead(!0)
            },
            updateCounter: function () {
                var unread = this.model.messages.getUnreadCount();
                0 === unread ? this.removeCounter() : (this.$el.addClass("unread"), this.trigger("title.rotate"))
            },
            removeCounter: function () {
                this.$el.removeClass("unread"), this.trigger("title.remove")
            },
            showTimestamp: function (message) {
                this.getMessageLI(message.cid).find(".chat-timestamp").show(), this.scrollConversation()
            },
            resetConversation: function () {
                var me = viewUtils.getUserJSON(inlineChat.getUser()),
                    user = viewUtils.getUserJSON(this.model.user),
                    conversationHTML = [];
                _.each(this.getMessagesJSON(), function (message) {
                    conversationHTML.push(this.getMessageHTML(message, {
                        me: me,
                        user: user
                    }))
                }.bind(this)), this.ui.conversation.empty().append(conversationHTML), this.scrollConversation()
            },
            serializeData: function () {
                var json = this.model.toJSON();
                return json.user = viewUtils.getUserJSON(this.model.user), json.messages = this.getMessagesJSON(), json.me = viewUtils.getUserJSON(inlineChat.getUser()), json.conversationHTML = [], _.each(json.messages, function (message) {
                    json.conversationHTML.push(this.getMessageHTML(message, {
                        me: json.me,
                        user: json.user
                    }))
                }.bind(this)), json.conversationHTML = json.conversationHTML.join(""), json
            },
            getMessageLI: function (cid) {
                return this.ui.conversation.find("[data-id=" + cid + "]")
            },
            getMessageHTML: function (message, users) {
                users = users || {};
                var me = users.me || viewUtils.getUserJSON(inlineChat.getUser()),
                    user = users.user || viewUtils.getUserJSON(this.model.user),
                    isTutor = !message.me && user.role == constants.ROLE.TUTOR,
                    userID = user.id,
                    username = user.chatName,
                    photo = user.photo,
                    attachment = null,
                    now = new Date,
                    timestamp = window.moment(message.timestamp).format("hh:mm A [on] dddd");
                return message.me && (username = "Me", photo = me.photo, userID = me.id), message.attachment && (attachment = message.attachment, attachment.ext = _.strRightBack(attachment.name, ".")), message.timestamp <= now.setDate(now.getDate() - 7) && (timestamp = window.moment(message.timestamp).format("hh:mm A [on] l")), this._messageTemplate({
                    id: message.cid,
                    timestamp: timestamp,
                    showTimestamp: message.showTimestamp,
                    text: _.linkify(_.escape(message.text), !0),
                    attachment: attachment,
                    action: viewUtils.getMessageActionHTML(message.action),
                    chatID: this.model.id,
                    userID: userID,
                    username: username,
                    photo: photo,
                    isTutor: isTutor
                })
            },
            getMessagesJSON: function () {
                return _.map(this.model.messages.models, function (model) {
                    return this.getMessageJSON(model)
                }.bind(this))
            },
            getMessageJSON: function (message) {
                var json = message.toJSON();
                return json.showTimestamp = this.model.isBot() || message.showTimestamp(), json.cid = message.cid, json
            },
            append: function (message) {
                this.ui.conversation.append(this.getMessageHTML(this.getMessageJSON(message))), this.scrollConversation(), message.isMe() || (this.ui.textarea.is(":focus") && document.hasFocus() && this.model.markAsRead(!0), this._playSound()), this.updateCounter()
            },
            _playSound: function () {
                !document.hasFocus() && chatConfig.soundsEnabled() && viewUtils.playChatSound()
            },
            showBlastMessageModal: function () {
                viewUtils.blastMessageModal.show()
            }
        }),
        ChatItem = BotItem.extend({
            template: "#chat-template",
            ui: {
                phrasebankButton: ".open-phrasebank",
                chatIcons: ".chat-icons",
                attachButton: ".chat-attach-button",
                attachDialog: ".chat-file-dialog",
                attachFile: ".chat-file",
                attachProgress: ".chat-attach-progress",
                attachProgressBar: ".chat-attach-progress .bar",
                attachText: ".chat-textarea-attachment",
                blockedMessage: ".chat-blocked-message",
                blockMenu: ".chat-block-user",
                btnMore: ".btn-more",
                busyMessage: ".chat-busy-message",
                chatActionButtons: ".chat-action-buttons li",
                container: ".chat-container",
                errorList: ".errorlist",
                form: ".chat-form",
                indicator: ".chat-indicator",
                meetNowButton: ".btn-meet-now",
                meetNowContainer: ".meet-now-container",
                meetNowProgress: ".meet-now-progress",
                meetNowSubject: ".meet-now-subject",
                meetNowSubjectForm: ".meet-now-subject-form",
                meetNowSubmit: ".submit-meet-now-proposal",
                moreDropdown: ".more-dropdown",
                nudge: ".chat-nudge",
                offlineMessage: ".chat-offline-message",
                onlineMessage: ".chat-online-message",
                scheduleButton: ".btn-schedule",
                typing: ".chat-typing-message",
                typingText: ".chat-text-entered-message",
                unblockedMessage: ".chat-unblocked-message",
                unblockMenu: ".chat-unblock-user"
            },
            events: {
                "click .btn-schedule": "showProposal",
                "click .chat-respond": "respondToProposal",
                "click .chat-attach-button": "toggleAttachment",
                "dblclick .chat-attach-button": "preventToggle",
                "click .open-phrasebank": "showPhrasebank",
                "dblclick .open-phrasebank": "preventToggle",
                "keydown textarea": "handleKeydown",
                "keyup textarea": "handleKeyup",
                "click .chat-action-buttons li a": "setActiveTab",
                "click @ui.meetNowButton": "toggleMeetNow",
                "click @ui.meetNowSubmit": "submitMeetNowProposal",
                "click .btn-more": "toggleMoreMenu",
                "click .chat-block-user": "toggleBlock",
                "click .chat-unblock-user": "toggleBlock",
                "click .more-dropdown a": "checkDisabledButton",
                "click .js-request-question": "requestQuestion"
            },
            modelEvents: {
                focus: "focusTextarea",
                "user:change:availability": "updateIndicator",
                "user:change:availableNow": "updateIndicator",
                "user:change:isBusy": "updateIndicator",
                "user:change:showInLesson": "showInLesson",
                "user:change:hasResponded": "updateMeetNow",
                "typing.started": "startedTyping",
                "typing.stopped": "stoppedTyping",
                "change:closeInitial": "closeInitial",
                "change:id": "idUpdated",
                "change:attachment": "attachmentChanged",
                "change:nudge": "nudgeChanged",
                "user:change:forwardsConnection": "forwardsConnectionChanged",
                "user:change:backwardsConnection": "backwardsConnectionChanged"
            },
            templateHelpers: {
                timezoneOffsetStr: function () {
                    return util.getTimezoneOffset(this.user.timezoneOffsetMinutes)
                }
            },
            initialize: function () {
                BotItem.prototype.initialize.call(this), this.typingTimeout = null, this.fileUploading = !1, this.toggleBlock = _.debounce(this._toggleBlock.bind(this), 250, !0)
            },
            onRender: function () {
                BotItem.prototype.onRender.call(this), this.ui.textarea.on("scroll", _.throttle(this.onTextareaScroll.bind(this), 10)), config.CONVERSATION_ID && config.CONVERSATION_ID == this.model.id && (this.minimize(), this.model.markAsRead()), this.setText(), this.$("[rel=tooltip]").tooltip()
            },
            onInsertedIntoDom: function () {
                this.initScrolling(), this.setupFileUpload(), this.model.user.forwardsConnection && this.forwardsConnectionChanged(), this.model.user.backwardsConnection && this.backwardsConnectionChanged(), this.isExpanded() ? this.adjustConversationHeight() : this.once("toggled", this.adjustConversationHeight.bind(this)), this.scrollConversation(), this.closeInitial(), this.model.newMessageSound.done(function () {
                    this._playSound()
                }.bind(this)), (this.model.user.isSuperuser() || this.model.user.isTutor() && inlineChat.getUser().isTutor()) && this.disableScheduling(), this.model.user.isParent() && this.ui.meetNowButton.disable().tooltip("fixTitle"), this.model.nudge() && this.nudgeChanged(), this.updateMeetNow(), this.$(".tooltip-target").tooltip(), this.attachmentChanged(), this.adjustConversationHeight()
            },
            append: function (message) {
                BotItem.prototype.append.call(this, message), this.checkOnlineMessage()
            },
            updateMeetNow: function () {
                meetNow.updateButtonsForUser(this.model.user)
            },
            resetConversation: function () {
                BotItem.prototype.resetConversation.apply(this, arguments), this.updateMeetNow()
            },
            nudgeChanged: function () {
                this.model.nudge() ? setTimeout(function () {
                    this.model.nudge() && (this.model.isTyping() ? setTimeout(this.nudgeChanged.bind(this), 1e3) : this.ui.nudge.fadeIn("fast"))
                }.bind(this), 1e3) : this.ui.nudge.fadeOut("fast")
            },
            setupFileUpload: function () {
                var self = this;
                util.fileUpload(this.ui.form, {
                    url: this.model.getFileUploadURL(),
                    afterChange: function (e, data) {
                        self.ui.attachText.hide(), data.context.hasAttachment || self.model.setAttachment(null)
                    },
                    beforeAdd: function () {
                        self.fileUploading = !0
                    },
                    done: function (e, data) {
                        self.ui.attachDialog.hide(), self.ui.attachButton.removeClass("pressed"), self.ui.textarea.focus(), self.model.setAttachment({
                            id: data.result.id,
                            url: data.result.url,
                            name: data.result.name
                        })
                    },
                    beforeFail: function (e, data) {
                        400 == data.jqXHR.status && (self.ui.attachText.html("").hide(), self.model.setAttachment(null))
                    },
                    always: function () {
                        self.ui.attachFile.show(), self.ui.attachProgress.hide(), self.fileUploading = !1
                    },
                    afterProgress: function () {
                        self.ui.attachFile.hide()
                    }
                })
            },
            attachmentChanged: function () {
                this.model.hasAttachment() ? (this.addAttachment(), this.ui.attachText.show(), this.adjustAttachmentIndent()) : (this.ui.attachText.hide(), this.ui.attachFile.val(""), this.adjustAttachmentIndent(!0))
            },
            adjustAttachmentIndent: function (reset) {
                reset ? this.ui.textarea.css("text-indent", "0px") : this.ui.textarea.css("text-indent", this.ui.attachText.outerWidth() + "px")
            },
            showPhrasebank: function (event) {
                phrasebank(this, this.ui.phrasebankButton, this.model.user.id, function (phraseText) {
                    this.focusTextarea(), this.setText(phraseText), this.scrollTextareaToBottom()
                }.bind(this), event.type, {
                    affix: !0
                })
            },
            toggleAttachment: function () {
                if (this.ui.attachButton.toggleClass("pressed"), this.ui.attachDialog.is(":visible")) this.ui.attachDialog.hide();
                else {
                    this.ui.attachDialog.show();
                    var buttonLeft = this.ui.attachButton.offset().left;
                    this.ui.attachDialog.offset({
                        left: buttonLeft - 179
                    });
                    var self = this;
                    util.triggerOnGlobalClick(function ($target) {
                        return $target.hasClass("chat-file")
                    }, function () {
                        self.ui.attachDialog.hide(), self.ui.attachButton.removeClass("pressed")
                    })
                }
                return !1
            },
            _getHeightAdjustment: function () {
                this.ui.conversation.removeAttr("style");
                var height = this.ui.conversation.height() - this.ui.messages.outerHeight(!0);
                return (this.model.user.isSuperuser() || !inlineChat.getUser().isAuthenticated()) && (height += 28), height
            },
            adjustConversationHeight: function () {
                if (!this.isClosed) {
                    var height = this._getHeightAdjustment(),
                        totalHeight = this.ui.conversation.scrollTop() + this.ui.conversation.height(),
                        atBottom = totalHeight == this.ui.conversation.prop("scrollHeight");
                    this.ui.conversation.height(height), atBottom && this.scrollConversation()
                }
            },
            showInLesson: function (user, show) {
                show && this.$el.show()
            },
            focusTextarea: function () {
                this.maximize(), this.ui.textarea.focus()
            },
            onTextareaScroll: function () {
                if (this.model.hasAttachment()) {
                    var scrollTop = this.ui.textarea.prop("scrollTop");
                    this.ui.attachText.css("top", -scrollTop)
                }
            },
            scrollTextareaToBottom: function () {
                this.ui.textarea.scrollTop(this.ui.textarea.prop("scrollHeight"))
            },
            showProposal: function () {
                var uniqueUrl = this.model.user.getUniqueNameURL();
                this.model.user.isBlocked() || this.model.user.isBlockingMe() || schedule.redirectIfParentWithoutStudent(uniqueUrl) || meetNow.showProposal(uniqueUrl)
            },
            _sendMessage: function () {
                var text = this.ui.textarea.val(),
                    hasAttachment = this.model.hasAttachment();
                if (!this.fileUploading && (!_.isBlank(text) || hasAttachment)) {
                    if (!inlineChat.getUser().isAuthenticated()) return signUpModal.show(this.model), !1;
                    this.model.pushMessage(text), this.ui.form[0].reset(), this.ui.textarea.val(""), this.ui.attachText.hide(), this.adjustAttachmentIndent(!0), this.checkOnlineMessage()
                }
                return this.stopTyping(), !1
            },
            handleKeydown: function (event) {
                if (event.keyCode === util.Event.KEY_TAB) return event.preventDefault(), this.tab = !0, void 0;
                if (this.tab && event.keyCode === util.Event.KEY_P) return this.shortcutPressed = !0, this.showPhrasebank(event), event.preventDefault(), void 0;
                if (util.isEnterKey(event) && !event.shiftKey) return this._sendMessage();
                var text = this.ui.textarea.val(),
                    hasAttachment = this.model.hasAttachment();
                event.keyCode == util.Event.KEY_BACK_SPACE && _.isBlank(text) && hasAttachment && this.model.setAttachment(null)
            },
            handleKeyup: function (event) {
                event.keyCode === util.Event.KEY_TAB && (event.preventDefault(), this.shortcutPressed || this.trigger("tabs.cycle", event.shiftKey), this.tab = !1, this.shortcutPressed = !1), this.makeRoomForScrollbar();
                var text = this.ui.textarea.val();
                if (this.model.setStoredText(text), event.keyCode === util.Event.KEY_ESCAPE) return this.end(), !1;
                var enterKey = util.isEnterKey(event) && !event.shiftKey;
                enterKey || _.isBlank(text) ? this.stopTyping() : (this.model.startTyping(), clearTimeout(this.typingTimeout), this.typingTimeout = setTimeout(this.stopTyping.bind(this), 3e3))
            },
            makeRoomForScrollbar: function () {
                if (!this.isClosed) {
                    var textarea = this.ui.textarea.get(0),
                        hasScrollBar = textarea.scrollHeight > textarea.clientHeight;
                    this.ui.textarea.toggleClass("with-scrollbar", hasScrollBar), this.ui.chatIcons.toggleClass("with-scrollbar", hasScrollBar)
                }
            },
            stopTyping: function () {
                if (clearTimeout(this.typingTimeout), !this.model.isClosed()) {
                    var text = this.ui.textarea.val();
                    this.model.stopTyping(!_.isBlank(text))
                }
            },
            setText: function (text) {
                text = text || this.model.getStoredText() || "", this.ui.textarea.val(text), this.stopTyping(), setTimeout(this.makeRoomForScrollbar.bind(this), 0)
            },
            truncate: function (message) {
                this.getMessageLI(message.cid).remove()
            },
            updateIndicator: function () {
                this.ui.indicator.removeClass(viewUtils.indicatorClasses).addClass("chat-" + viewUtils.getIndicatorClass(this.model.user)).attr("data-original-title", viewUtils.getIndicatorTitle(this.model.user)), this.updateMeetNow(), this.checkOfflineMessage(), this.scrollConversation()
            },
            checkOfflineMessage: function () {
                this.model.user.isOffline() ? (this.ui.busyMessage.hide(), this.ui.offlineMessage.show(), this.ui.typing.hide(), this.ui.typingText.hide()) : this.model.user.isBusy() ? (this.ui.busyMessage.show(), this.ui.offlineMessage.hide()) : (this.ui.busyMessage.hide(), this.ui.offlineMessage.hide()), this.adjustConversationHeight()
            },
            checkOnlineMessage: function () {
                if (inlineChat.getUser().isStudentOrParent() && this.model.user.isTutor() && !this.model.user.isAvailableNow() && !this.model.user.isOffline()) {
                    var hasTalked = this.model.otherUserHasTalked();
                    this.ui.onlineMessage.is(":visible") && hasTalked ? this.ui.onlineMessage.hide() : this.ui.onlineMessage.is(":hidden") && !hasTalked && this.ui.onlineMessage.show(), this.adjustConversationHeight()
                }
            },
            idUpdated: function () {
                this.$("[data-uid]").data("uid", this.model.user.id)
            },
            startedTyping: function () {
                this.isClosed || (this.ui.typingText.hide(), this.ui.typing.show(), this.adjustConversationHeight())
            },
            stoppedTyping: function (textEntered) {
                this.isClosed || (this.ui.typing.hide(), this.ui.typingText[textEntered ? "show" : "hide"](), this.adjustConversationHeight())
            },
            setActiveTab: function (event) {
                event.preventDefault();
                var $target = $(event.target).parent();
                $target.hasClass("active") ? $target.removeClass("active") : (this.ui.chatActionButtons.removeClass("active"), $target.hasClass("btn-schedule") || $target.addClass("active")), $target.hasClass("btn-meet-now") || this.ui.meetNowSubjectForm.hide(), $target.hasClass("btn-more") || this.hideMoreMenu()
            },
            toggleMeetNow: function (event) {
                if (meetNow.hasPendingRequest()) return !1;
                var $target = $(event.target).parent();
                return $target.hasClass("active") ? (this.ui.meetNowContainer.show(), this.ui.meetNowSubjectForm.show(), this.ui.meetNowProgress.hide(), this.setupMeetNowSubjects()) : this.ui.meetNowContainer.hide(), !1
            },
            setupMeetNowSubjects: function () {
                var studentID, tutorID;
                inlineChat.getUser().isTutor() ? (tutorID = inlineChat.getUser().id, studentID = this.model.user.id) : (studentID = inlineChat.getUser().id, tutorID = this.model.user.id), meetNow.setupSubjects(this.ui.meetNowSubject, tutorID, studentID)
            },
            disableScheduling: function () {
                this.ui.meetNowButton.disable(), this.ui.meetNowContainer.hide(), this.ui.scheduleButton.disable();
                var name = this.model.user.getName();
                this.model.user.isBlockingMe() && this.ui.scheduleButton.tooltip({
                    title: _.sprintf("You cannot schedule with %s at this time", name)
                }), this.model.user.isBlocked() && this.ui.scheduleButton.tooltip({
                    title: _.sprintf("You have blocked %s", name)
                })
            },
            enableScheduling: function () {
                this.ui.meetNowButton.enable(), this.ui.scheduleButton.enable(), this.ui.scheduleButton.tooltip("disable")
            },
            toggleMoreMenu: function () {
                if (this.ui.btnMore.hasClass("active")) {
                    var self = this;
                    this.showMoreMenu(), util.triggerOnGlobalClick(function ($target) {
                        return $target.closest(".more-dropdown").is(self.ui.moreDropdown)
                    }, function () {
                        self.hideMoreMenu()
                    }, {
                        ignoreCallback: function ($target) {
                            return $target.closest(".btn-more").is(self.ui.btnMore)
                        }
                    })
                } else this.hideMoreMenu();
                return !1
            },
            showMoreMenu: function () {
                this.ui.moreDropdown.show(), this.ui.btnMore.addClass("active")
            },
            hideMoreMenu: function () {
                this.isClosed || (this.ui.moreDropdown.hide(), this.ui.btnMore.removeClass("active"))
            },
            submitMeetNowProposal: function (event) {
                var subjectID = this.ui.meetNowSubject.val();
                if (_.isBlank(subjectID)) this.ui.meetNowSubjectForm.find(".chzn-container").addClass("error");
                else {
                    var $target = $(event.target),
                        self = this;
                    $target.disable(), this.ui.meetNowSubjectForm.find(".chzn-container").removeClass("error"), this.ui.meetNowSubjectForm.hide(), this.ui.errorList.empty().hide(), meetNow.submit(this.model.user.id, this.model.user.getName(), subjectID, {
                        context: "chat",
                        $progress: this.ui.meetNowProgress,
                        onCreate: function () {
                            self.ui.meetNowButton.removeClass("active"), self.ui.meetNowContainer.slideUp(800, function () {
                                $target.enable()
                            })
                        },
                        onCancel: function () {
                            self.ui.meetNowProgress.hide(), self.ui.meetNowSubjectForm.show(), $target.enable()
                        },
                        onError: function () {
                            self.ui.meetNowButton.removeClass("active"), self.ui.meetNowContainer.slideUp(800)
                        }
                    })
                }
            },
            haveLessonsScheduledModal: function () {
                var model = this.model,
                    name = viewUtils.getUserJSON(model).name;
                $blockUserLessonsModal.find(".user-name").each(function () {
                    this.text(name)
                }), $blockUserLessonsModal.modal("show")
            },
            checkDisabledButton: function () {
                return !this.ui.moreDropdown.hasClass("disabled")
            },
            requestQuestion: function () {
                return inlineChat.getUser().isTutor() && Backbone.trigger("chat:request.question", this.model.user), this.hideMoreMenu(), !1
            },
            _toggleBlock: function () {
                this.hideMoreMenu(), this.model.user.toggleBlocked()
            },
            forwardsConnectionChanged: function () {
                var forwardsConnection = this.model.user.forwardsConnection,
                    previousState = forwardsConnection.previous("state");
                forwardsConnection.hasLessonScheduled() ? (this.forwardsUnblockedUI(), this.ui.unblockedMessage.hide(), this.forwardsBlockableUI(), this.haveLessonsScheduledModal()) : forwardsConnection.isBlocked() ? this.forwardsBlockedUI() : previousState == constants.CONNECTION_STATE.BLOCKED ? this.forwardsUnblockedUI() : this.forwardsBlockableUI()
            },
            backwardsConnectionChanged: function () {
                var backwardsConnection = this.model.user.backwardsConnection,
                    previousState = backwardsConnection.previous("state");
                backwardsConnection.isBlocked() ? this.backwardsBlockedUI() : previousState && this.backwardsUnblockedUI()
            },
            backwardsBlockedUI: function () {
                this.stoppedTyping(), this.disableScheduling(), this.model.user.updateAvailability({
                    availability: constants.AVAILABILITY.OFFLINE
                })
            },
            backwardsUnblockedUI: function () {
                this.enableScheduling(), this.model.user.resyncAvailability()
            },
            forwardsBlockableUI: function () {
                this.ui.blockMenu.show()
            },
            forwardsBlockedUI: function () {
                this.model.user.updateAvailability({
                    availability: constants.AVAILABILITY.OFFLINE
                }), this.stoppedTyping(), this.disableScheduling(), this.ui.blockMenu.hide(), this.ui.unblockMenu.show(), this.ui.unblockedMessage.hide(), this.ui.messages.children().hide(), this.ui.blockedMessage.show(), this.adjustConversationHeight(), this.updateMeetNow()
            },
            forwardsUnblockedUI: function () {
                this.model.user.resyncAvailability(), this.enableScheduling(), this.ui.blockMenu.show(), this.ui.unblockMenu.hide(), this.ui.unblockedMessage.show(), this.ui.blockedMessage.hide(), this.adjustConversationHeight(), this.updateMeetNow()
            }
        }),
        ChatUser = Backbone.Marionette.ItemView.extend({
            template: "#omnibar-user",
            tutorMetaTemplate: "#omnibar-tutor-meta",
            suMetaTemplate: "#omnibar-su-meta",
            tagName: "li",
            className: "hidden-content",
            ui: {
                chatIndicator: ".chat-indicator",
                removeUser: ".remove-user",
                undoBar: ".undo-bar",
                userName: ".user-name",
                lessonTime: ".latest-lesson-time",
                userInfo: ".user-info",
                userImage: ".user-image"
            },
            events: {
                click: "openChat",
                "click .remove-user": "removeUser",
                "click .undo-remove-user": "undoRemoveUser"
            },
            modelEvents: {
                show: "show",
                hide: "hide",
                destroy: "destroy",
                "change:availability": "updateIndicator",
                "change:availableNow": "updateIndicator",
                "change:isBusy": "updateIndicator",
                "change:showInLesson": "showInLesson",
                "change:forwardsConnection": "checkForwardsConnection",
                "editmode:enable": "enableEditMode",
                "editmode:disable": "disableEditMode"
            },
            templateHelpers: {
                latestLessonDateFormat: function () {
                    return config.addLessonsMetaOnOmnibar ? util.dateFormatPrettyfier(this.lessonLatestTime) : ""
                }
            },
            initialize: function () {
                this._tutorMetaTemplate = Backbone.Marionette.TemplateCache.get(this.tutorMetaTemplate), this._suMetaTemplate = Backbone.Marionette.TemplateCache.get(this.suMetaTemplate)
            },
            onRender: function () {
                this.fadeIn(), this.model.isSuperuser() || (inlineChat.getUser().isTutor() || inlineChat.getUser().isSuperuser()) && this.ui.userName.tooltip({
                    container: "#omnibar",
                    placement: "left",
                    delay: {
                        show: 250,
                        hide: 0
                    }
                }), this.canShow() ? this.model.forwardsConnection && this.checkForwardsConnection() : this.hide(), inlineChat.isEditMode() && this.enableEditMode()
            },
            onBeforeClose: function () {
                this.ui.userName.tooltip("destroy")
            },
            canShow: function () {
                return !config.OMNIBAR_SU_ONLY || this.model.isSuperuser() || this.model.showInLesson()
            },
            fadeIn: function () {
                this.$el.fadeIn("fast")
            },
            destroy: function () {
                this.$el.fadeOut("fast", function () {
                    this.close()
                }.bind(this))
            },
            show: function () {
                this.$el.show()
            },
            hide: function () {
                this.$el.hide()
            },
            showInLesson: function (user, show) {
                show && this.show()
            },
            openChat: function () {
                if (inlineChat.isEditMode() && this.model.isHidden()) return !1;
                var chat = inlineChat.openChat(this.model);
                return chat.trigger("maximize"), chat.trigger("focus"), !0
            },
            updateIndicator: function () {
                this.ui.chatIndicator.removeClass(viewUtils.indicatorClasses).addClass("chat-" + viewUtils.getIndicatorClass(this.model))
            },
            checkForwardsConnection: function () {
                inlineChat.isEditMode() || (!this.canShow() || this.model.isHidden() || this.model.isBlocked() ? this.hide() : this.model.isNormal() && this.show())
            },
            enableEditMode: function () {
                this.ui.removeUser.show()
            },
            disableEditMode: function () {
                this.ui.removeUser.hide()
            },
            removeUser: function () {
                return this.model.hideUser(), this.ui.userInfo.fadeOut(50, function () {
                    this.$el.addClass("user-removed"), this.ui.undoBar.fadeIn(), hiddenUsers.add(this)
                }.bind(this)), !1
            },
            undoRemoveUser: function () {
                return this.model.unhideUser(), this.ui.undoBar.fadeOut(50, function () {
                    this.$el.removeClass("user-removed"), this.ui.userInfo.fadeIn(), hiddenUsers.remove(this)
                }.bind(this)), !1
            },
        }),
        EmptySuperuserView = Backbone.Marionette.ItemView.extend({
            template: "#omnibar-su-empty",
            tagName: "li",
            className: "su-empty",
            serializeData: function () {
                return {
                    photo: inlineChat.cache.getSuperuserAvatar()
                }
            }
        }),
        ChatUserGroup = Backbone.Marionette.CollectionView.extend({
            itemView: ChatUser,
            appendHtml: function (c, v, i) {
                this.sortedAppend(c, v, i, !0)
            }
        }),
        ChatSuperuserGroup = ChatUserGroup.extend({
            emptyView: EmptySuperuserView
        }),
        ChatGroup = Backbone.Marionette.ItemView.extend({
            template: "#omnibar-group",
            tagName: "div",
            initialize: function () {
                this.userListHidden = !0
            },
            className: function () {
                var classes = ["user-group"];
                return this.model.isSubjectSection() ? classes.push("subject-section") : this.model.isSuperuser() ? classes.push("support-team") : classes.push("my-users", "temp-divide"), classes.join(" ")
            },
            ui: {
                noUsers: ".no-users",
                userList: ".user-list",
                showMore: ".show-more",
                spinner: ".spinner"
            },
            events: {
                "click .show-more": "getMoreUsers"
            },
            modelEvents: {
                "users:add": "checkUsers",
                "users:remove": "checkUsers",
                hide: "hide",
                show: "show",
                "users:change:showInLesson": "showInLesson"
            },
            checkUsers: function () {
                (!config.OMNIBAR_SU_ONLY || this.model.isSuperuser()) && (this.model.users.length > 0 && this.userListHidden ? this.show() : 0 !== this.model.users.length || this.userListHidden || this.hide())
            },
            show: function () {
                _.isBlank(this.ui.noUsers.text()) ? this.$el.show() : (this.ui.noUsers.hide(), this.ui.userList.show(), this.userListHidden = !1)
            },
            hide: function () {
                _.isBlank(this.ui.noUsers.text()) ? this.$el.hide() : (this.ui.noUsers.show(), this.ui.userList.hide(), this.userListHidden = !0)
            },
            showInLesson: function (user, show) {
                show && this.$el.show()
            },
            getMoreUsers: function () {
                if (this.model.isSubjectSection()) {
                    var self = this;
                    self.ui.spinner.show(), this.model.getNewUser({
                        count: 3,
                        complete: function (data) {
                            data.hasMore ? self.ui.spinner.hide() : self.ui.showMore.fadeOut()
                        }
                    })
                }
            },
            getUserGroupClass: function () {
                return this.model.isSuperuser() ? ChatSuperuserGroup : ChatUserGroup
            },
            onRender: function () {
                !config.OMNIBAR_SU_ONLY || this.model.isSuperuser() || this.model.showInLesson() || this.$el.hide();
                var UserGroup = this.getUserGroupClass();
                this.userGroup = new UserGroup({
                    el: this.ui.userList,
                    collection: this.model.users
                }), this.userGroup.render(), this.checkEmpty()
            },
            checkEmpty: function () {
                if (0 === this.model.users.length && !this.model.isSuperuser()) {
                    var text = "";
                    switch (this.model.getRole()) {
                    case constants.ROLE.STUDENT:
                        text = omnibar.ui.noStudent.text();
                        break;
                    case constants.ROLE.PARENT:
                        text = omnibar.ui.noParent.text();
                        break;
                    default:
                        this.$el.hide()
                    }
                    _.isBlank(text) || (this.ui.noUsers.text(text).show(), this.ui.userList.hide())
                }
            },
            serializeData: function () {
                var _proto = Backbone.Marionette.ItemView.prototype,
                    json = _proto.serializeData.apply(this, arguments);
                return json.userCount = null, json
            }
        }),
        OmnibarGroups = Backbone.Marionette.CollectionView.extend({
            itemView: ChatGroup,
            appendHtml: function (c, v, i) {
                this.sortedAppend(c, v, i, !0)
            },
            onRender: function () {
                util.scrollLock(this.$el)
            }
        }),
        Omnibar = Backbone.Marionette.View.extend({
            CONTENT_WIDTH: 940,
            TOP_PADDING: 40,
            ui: {
                header: ".chat-header",
                body: ".chat-body",
                settings: ".chat-settings",
                settingsButton: ".chat-settings-button",
                chatSounds: ".chat-sounds",
                chatEdit: ".chat-edit",
                editmodeSignpost: ".editmode-signpost",
                minimize: ".chat-header .chat-minimize i",
                chatName: ".chat-header .chat-name",
                refresh: ".chat-header .icon-refresh",
                input: '.chat-header input[type="text"]',
                noStudent: ".no-student",
                noParent: ".no-parent",
                noTutor: ".no-tutor"
            },
            events: {
                "click .chat-header": "maybeToggle",
                "click .chat-name": "maybeToggle",
                "click .chat-minimize": "toggle",
                "click .chat-settings-button": "toggleSettingsVisibility",
                "click .chat-sounds": "toggleChatSounds",
                "click .chat-edit": "enterEditMode",
                "click .editmode-end": "exitEditMode"
            },
            initialize: function (options) {
                this.bindUIElements(), this.groups = options.groups, this.listenTo(Backbone, "omnibar:minimizeIfNotDocked", this.minimizeIfNotDocked)
            },
            render: function () {
                this.spinner = new window.Spinner(this.getSpinnerOptions()), this.startSpinner(), this.$el.show();
                var reflow = _.throttle(this.reflow.bind(this), 10);
                $(window).on("resize", function () {
                    reflow()
                }), this.reflowThrottled = reflow, this.rendering = !0, chatConfig.done(function () {
                    this.reflowThrottled();
                    var expanded = chatConfig.omnibarMaximized();
                    if (null !== expanded || inlineChat.getUser().isAuthenticated())!expanded || config.OMNIBAR_SU_ONLY ? this.minimize() : config.omnibarMinimized && this.minimize();
                    else {
                        var minimize = !this.isDocked();
                        minimize ? this.minimize() : this.maximize(), window.mixpanelTrack("Signed Out Omnibar", {
                            expanded: !minimize
                        })
                    }
                    this.rendering = !1
                }.bind(this))
            },
            close: function () {
                return this.undock(!0), Backbone.Marionette.View.prototype.close.apply(this, arguments)
            },
            getSpinnerOptions: function () {
                return {
                    lines: 13,
                    length: 4,
                    width: 2,
                    radius: 4,
                    rotate: 20,
                    color: "#000",
                    speed: 1,
                    trail: 97,
                    shadow: !1,
                    hwaccel: !0,
                    top: 2,
                    left: 70
                }
            },
            startSpinner: function () {
                this.ui.refresh.hide(), this.spinner.spin(this.ui.header[0])
            },
            stopSpinner: function () {
                this.ui.refresh.show(), this.spinner.stop()
            },
            toggle: function () {
                this.ui.body.is(":visible") ? this.minimize() : this.maximize()
            },
            maybeToggle: function (event) {
                $(event.target).hasClass("chat-header") && this.toggle()
            },
            minimizeIfNotDocked: function () {
                !this.isDocked() && this.isExpanded() && this.minimize()
            },
            minimize: function () {
                this.rendering || chatConfig.omnibarMaximized(!1), this.ui.body.hide(), this.ui.minimize.removeClass("minimize-chatlist-icon").addClass("maximize-chatlist-icon"), this.$el.removeClass("expanded"), this.isDocked() && $("body").removeClass("omnibar-docked"), this.reflowThrottled()
            },
            maximize: function () {
                this.rendering || chatConfig.omnibarMaximized(!0), this.ui.body.show(), this.ui.minimize.removeClass("maximize-chatlist-icon").addClass("minimize-chatlist-icon"), this.$el.addClass("expanded"), this.isDocked() && $("body").addClass("omnibar-docked"), this.reflowThrottled()
            },
            isExpanded: function () {
                return this.$el.hasClass("expanded")
            },
            isDocked: function () {
                return this.$el.hasClass("docked")
            },
            dock: function () {
                this.ui.body.css({
                    "max-height": "none"
                }), this.$el.addClass("docked"), $("body").addClass("omnibar-docked"), this.maximize()
            },
            undock: function (closing) {
                this.$el.removeClass("docked"), $("body").removeClass("omnibar-docked"), closing || this.minimize()
            },
            reflow: function () {
                var left = this.$el.position().left,
                    contentWidth = this.CONTENT_WIDTH;
                if (contentWidth >= left) {
                    this.isDocked() && this.undock();
                    var heightMod = util.topNavHeight + this.TOP_PADDING,
                        maxHeight = $(window).height() - this.ui.header.height() - heightMod;
                    this.ui.body.css("max-height", maxHeight), this.isExpanded() && this.ui.body.height() > maxHeight ? this.$el.css("top", heightMod) : this.$el.css("top", "auto")
                } else left > contentWidth && !this.isDocked() && this.dock();
                Backbone.trigger("omnibar.reflow")
            },
            toggleChatSounds: function () {
                var chatSounds = this.ui.chatSounds,
                    enabled = chatSounds.hasClass("enabled");
                chatSounds[enabled ? "removeClass" : "addClass"]("enabled"), chatConfig.updateChatSounds(!enabled, function () {
                    chatSounds[enabled ? "addClass" : "removeClass"]("enabled")
                })
            },
            enterEditMode: function () {
                if (this.$el.hasClass("editmode")) return this.exitEditMode(), void 0;
                inlineChat.enableEditMode(), this.ui.settings.hide(), this.ui.settingsButton.removeClass("active"), this.ui.chatEdit.addClass("enabled"), this.$el.addClass("editmode"), this.maximize(), this.ui.body.find(".subject-section").fadeOut("fast", function () {
                    $(this).hide()
                });
                var counter = 0;
                this.ui.body.find(".my-users .user-list .remove-user").show().each(function () {
                    var $el = $(this).closest(".user-info");
                    setTimeout($el.addClass.bind($el, "editmode-active"), 30 * counter++)
                })
            },
            exitEditMode: function () {
                this.$el.hasClass("editmode") && (hiddenUsers.hideHiddenUsers(), inlineChat.disableEditMode(), this.ui.settings.hide(), this.ui.settingsButton.removeClass("active"), this.ui.chatEdit.removeClass("enabled"), this.$el.removeClass("editmode"), this.ui.body.find(".user-info").removeClass("editmode-active"), this.ui.body.find(".subject-section").fadeIn("fast"))
            },
            toggleSettingsVisibility: function () {
                this.ui.settings.toggle();
                var visible = this.ui.settings.is(":visible");
                if (visible) {
                    this.ui.settingsButton.addClass("active");
                    var self = this;
                    util.triggerOnGlobalClick(function ($target) {
                        return $target.closest(self.ui.settings).exists()
                    }, function () {
                        self.ui.settings.hide(), self.ui.settingsButton.removeClass("active")
                    })
                } else this.ui.settingsButton.removeClass("active");
                return !1
            }
        }),
        ChatWindows = Backbone.Marionette.CollectionView.extend({
            getItemView: function (model) {
                return model.isBot() ? BotItem : ChatItem
            },
            chatSize: {
                width: 260,
                margin: 5
            },
            collectionEvents: {
                "queue.push": "itemQueued"
            },
            initialize: function () {
                this.appendHtml = this.sortedAppend, this.on("itemview:title.rotate", function (view) {
                    (!config.OMNIBAR_SU_ONLY || view.model.user.isSuperuser()) && notifications.addTabTitle(view.model)
                }), this.on("itemview:title.remove", function (view) {
                    notifications.removeTabTitle(view.model)
                }), this.on("itemview:tabs.cycle", this.cycleTabs);
                var reflow = _.throttle(this.reflow.bind(this), 100);
                this.on("item:removed", reflow), $(window).on("resize", function () {
                    reflow()
                })
            },
            cycleTabs: function (view, shiftKey) {
                events.create(events.EVENT.CYCLE_CHAT_WINDOWS);
                var len = this.collection.length,
                    index = this.collection.indexOf(view.model);
                if (len > 1) {
                    var next = 0 === index ? len - 1 : index - 1;
                    shiftKey && (next = index + 1 === len ? 0 : index + 1), this.collection.at(next).trigger("focus")
                }
            },
            onRender: function () {
                var right = 0;
                omnibar.$el.exists() && (right += omnibar.$el.outerWidth() + parseInt(omnibar.$el.css("right")) + 20), this.$el.css("right", right + "px"), this.reflow(!0)
            },
            onAfterItemAdded: function (view) {
                Backbone.trigger("phrasebank:close"), view.onInsertedIntoDom(), this.collection.length > 0 && $("body").addClass("with-chat");
                var toQueue = this.getQueueStatus();
                toQueue > 0 && this.collection.queueChat(toQueue, !0)
            },
            getQueueStatus: function () {
                var width = this.$el.position().left + this.$el.width(),
                    chatSize = this.chatSize.width + this.chatSize.margin,
                    openChats = this.collection.length,
                    possibleChats = Math.floor(width / chatSize);
                return openChats - possibleChats
            },
            reflow: function (byActivity) {
                byActivity = !!byActivity;
                var toQueue = this.getQueueStatus();
                toQueue > 0 ? this.collection.queueChat(toQueue, byActivity) : 0 > toQueue && this.collection.queue.length > 0 && this.collection.unqueueChat(-toQueue)
            },
            itemQueued: function (index, wasFocused) {
                if (wasFocused) {
                    var len = inlineChat.chats.length;
                    len && inlineChat.chats.at(Math.min(index, len - 1)).trigger("focus")
                }
            }
        });
    config.isAuthenticated || (signUpModal = baseViews.SignUpModal("js-chat-carrot", {
        onSuccess: function (data, chat) {
            inlineChat.deferMessage(chat, function () {
                window.location.href = data.nextURL
            })
        },
        onHide: function (chat) {
            chat.trigger("focus")
        }
    }));
    var CLASSES = {
            InlineChat: models.InlineChat,
            ChatWindows: ChatWindows,
            OmnibarGroups: OmnibarGroups,
            Omnibar: Omnibar
        },
        init = function (userID, uniqueID, userName, userPhoto, userRole, isSuperuser, soundsEnabled) {
            if (config.loginRequired || window.amplify.store("user.signedout")) return window.amplify.store("user.signedout", null), void 0;
            chatConfig.soundsEnabled(soundsEnabled), inlineChat = new CLASSES.InlineChat({
                id: uniqueID,
                userID: userID,
                name: userName,
                photo: userPhoto,
                role: userRole,
                su: isSuperuser,
                availability: constants.AVAILABILITY.ONLINE
            }), $blockUserLessonsModal = $("#block-user-lessons-modal");
            var $omnibar = $("#omnibar"),
                windows = new CLASSES.ChatWindows({
                    el: $("#chat-bar"),
                    collection: inlineChat.chats
                }),
                groupView = new CLASSES.OmnibarGroups({
                    el: $omnibar.find(".chat-body"),
                    collection: inlineChat.groups
                });
            return omnibar = new CLASSES.Omnibar({
                el: $omnibar,
                groups: groupView
            }), inlineChat.progress(function () {
                windows.render(), groupView.render(), omnibar.render(), inlineChat.synchronize().done(function () {
                    omnibar.stopSpinner()
                }), inlineChat.resolve()
            }), inlineChat.checkLesson(), $("#sign-out").on("click", function () {
                inlineChat.signOut(!0)
            }), Backbone.on("chat.signout", function () {
                windows.close(), groupView.close(), omnibar.close()
            }), Backbone.on("chat:request.question", function (student) {
                viewUtils.tutorRequestQuestion(inlineChat.getUser(), student)
            }), config.supportPaywallMessage && setTimeout(function () {
                Backbone.trigger("chat:su-message", constants.MESSAGE_CONTEXT.SU_PAYWALL, "left-page")
            }, 5e3), inlineChat
        };
    return {
        BotItem: BotItem,
        ChatItem: ChatItem,
        ChatUser: ChatUser,
        ChatGroup: ChatGroup,
        ChatUserGroup: ChatUserGroup,
        OmnibarGroups: OmnibarGroups,
        ChatWindows: ChatWindows,
        Omnibar: Omnibar,
        CLASSES: CLASSES,
        init: init,
        postInit: function (chatData) {
            config.update({
                isAuthenticated: !0
            });
            var user = chatData.userInfo;
            chatConfig.soundsEnabled(user.soundsEnabled), inlineChat = init(user.userID, user.id, user.name, user.photo, user.role, !1), inlineChat.loadChats(chatData.chats || {})
        }
    }
}), define("chat/models/chats", ["base/models", "chat/constants", "chat/models/users", "chat/models/util", "config", "util"], function (baseModels, constants, users, chatUtil, config, util) {
    var Message = Backbone.NoSync.Model.extend({
            defaults: {
                text: "",
                attachment: null,
                me: !1,
                timestamp: null,
                synced: !0,
                read: !1,
                action: null
            },
            initialize: function () {
                this.retries = 0, this._showTimestamp = !1, _.isString(this.getTimestamp()) && this.set("timestamp", new Date(this.getTimestamp()))
            },
            isMe: function () {
                return !!this.get("me")
            },
            getAction: function () {
                return this.get("action")
            },
            getText: function () {
                return this.get("text")
            },
            getTimestamp: function () {
                return this.get("timestamp")
            },
            showTimestamp: function (show) {
                return show === !0 && (this._showTimestamp = !0, this.trigger("show.timestamp", this)), this._showTimestamp
            }
        }),
        Messages = Backbone.Collection.extend({
            model: Message,
            MAX_MESSAGES: 20,
            SHOW_TIMESTAMP_AFTER: 120,
            SHOW_OLD_TIMESTAMP_AFTER: 3600,
            comparator: "id",
            initialize: function () {
                this.showTimestamp = null
            },
            setTimestampTrigger: function (showNow) {
                clearTimeout(this.showTimestamp), this.showTimestamp = setTimeout(function () {
                    var last = this.last();
                    last && last.showTimestamp(!0)
                }.bind(this), showNow ? 0 : 1e3 * this.SHOW_TIMESTAMP_AFTER)
            },
            pushMessage: function (data, push) {
                var lastMessage = this.last();
                if (lastMessage && lastMessage.getText() == data.text && _.isString(lastMessage.id) && lastMessage.id.match(/^t\d+/)) {
                    var sameAttachment = data.attachment && lastMessage.has("attachment") && lastMessage.get("attachment").url == data.attachment.url,
                        noAttachment = !data.attachment && !lastMessage.has("attachment");
                    if (sameAttachment || noAttachment) return lastMessage
                }
                var message = this.get(data.id);
                if (message) return message;
                var fields = _.extend({
                    id: "t" + _.random(0, 9999999),
                    timestamp: new Date,
                    read: !!data.me,
                    synced: !push
                }, data);
                return message = new Message(fields), this.push(message), this.postPush(), push && this.trigger("push"), message
            },
            postPush: function (fetched) {
                if (this.setTimestampTrigger(fetched), this.length > this.MAX_MESSAGES) {
                    var count = this.length - this.MAX_MESSAGES;
                    _.times(count, this.shift.bind(this))
                }
                fetched && this.each(function (message) {
                    message.showTimestamp(this.shouldShowTimestamp(message))
                }.bind(this)), this.trigger("save")
            },
            synchronize: function (messages) {
                _.each(messages, function (message) {
                    message.synced = !0
                }), this.set(messages, {
                    remove: !1,
                    silent: !0
                }), this.postPush(!0), this.trigger("refresh")
            },
            getLastSynced: function () {
                return _.last(this.where({
                    synced: !0
                }))
            },
            getUnsynced: function () {
                return this.where({
                    synced: !1
                })
            },
            getUnreadCount: function () {
                return this.where({
                    read: !1
                }).length
            },
            getLastTimestamp: function () {
                var lastMsg = this.last();
                return lastMsg ? lastMsg.getTimestamp() : 0
            },
            shouldShowTimestamp: function (message) {
                var index = this.indexOf(message);
                if (0 === index) return 1 === this.length;
                var prevMessage = this.at(index - 1),
                    diff = (message.getTimestamp() - prevMessage.getTimestamp()) / 1e3;
                return diff > this.SHOW_OLD_TIMESTAMP_AFTER
            }
        }),
        Chat = Backbone.Model.extend({
            DESTROY_WAIT_TIME: 30,
            defaults: {
                dateActive: null,
                userID: 0,
                minimized: !1,
                destroyed: !1,
                attachment: null
            },
            initialize: function () {
                this.syncing = !1, this.destroying = null, this.user = null, this.messages = null, this._isTyping = !1, this.setupNewMessageSound(), this.getDateActive() || this.setDateActive(new Date), this.autosave();
                var user = null;
                _.isString(this.id) && this.id.match(/^bot/) ? user = users.Cache.getBot(this.id.substring(3)) : this.has("user") ? (user = users.Cache.getUser(this.get("user")), this.unset("user")) : this.has("userID") && (user = users.Cache.get(this.get("userID"))), user && this.setUser(user), this.setupMessages(), this.sendMessage(), this.startTyping = _.debounce(this._startTyping.bind(this), 250, !0)
            },
            setUser: function (user) {
                this.user = user, this.set("userID", user.id), this.user.chat = this, this.eventPassthrough(this.user, "user:"), this.hasTempID() ? this.user.hasExistingChat() && this.updateID(this.user.getChatID()) : (this.user.isBot() || this.subscribe(), this.user.setChatID(this.id))
            },
            isBot: function () {
                return !(!this.user || !this.user.isBot())
            },
            setupNewMessageSound: function () {
                return this.newMessageSound = new $.Deferred, this.newMessageSound
            },
            hasTempID: function () {
                return !this.id || String(this.id).indexOf("-") > -1
            },
            getSocketRoom: function () {
                return "chat=" + this.id
            },
            subscribe: function () {
                var events = {},
                    self = this;
                events["typing:user=" + this.user.id] = function () {
                    self.trigger("typing.started")
                }, events["stopped-typing:user=" + this.user.id] = function (textEntered) {
                    self.trigger("typing.stopped", textEntered)
                }, chatUtil.chatSocket.subscribe(this.getSocketRoom(), events)
            },
            unsubscribe: function () {
                chatUtil.chatSocket.unsubscribe(this.getSocketRoom())
            },
            shouldEmitTyping: function () {
                return !this.user || this.isClosed() ? !1 : !this.user.isBlocked() && !this.user.isBlockingMe()
            },
            _startTyping: function () {
                this._isTyping = !0, this.shouldEmitTyping() && chatUtil.chatSocket.emitToRoom(this.getSocketRoom(), _.sprintf("typing:user=%s", users.Cache.currentUser.id))
            },
            stopTyping: function (textEntered) {
                this._isTyping = !1, this.shouldEmitTyping() && chatUtil.chatSocket.emitToRoom(this.getSocketRoom(), _.sprintf("stopped-typing:user=%s", users.Cache.currentUser.id), textEntered)
            },
            isTyping: function () {
                return this._isTyping
            },
            getLastActivity: function () {
                var lastMsg = this.messages.getLastTimestamp(),
                    started = this.getDateActive();
                return lastMsg > started ? lastMsg : started
            },
            setDateActive: function (dateActive) {
                return _.isString(dateActive) && (dateActive = new Date(dateActive)), this.set("dateActive", dateActive), dateActive
            },
            getDateActive: function () {
                var dateActive = this.get("dateActive");
                return _.isString(dateActive) && (dateActive = this.setDateActive(dateActive)), dateActive
            },
            hasUnreadMessages: function () {
                return this.messages.getUnreadCount() > 0
            },
            otherUserHasTalked: function () {
                return this.messages.where({
                    me: !1
                }).length > 0
            },
            sync: function () {
                return this.collection ? Backbone.Model.prototype.sync.apply(this, arguments) : !0
            },
            closeInitial: function (close) {
                return null === close ? this.unset("closeInitial") : (close === !0 || close === !1) && this.set("closeInitial", close), !!this.get("closeInitial")
            },
            isClosed: function () {
                return !!this.get("destroyed")
            },
            destroyed: function (destroy) {
                return destroy === !0 ? (this.set("destroyed", !0), this.destroying = setTimeout(this.destroy.bind(this), 1e3 * this.DESTROY_WAIT_TIME)) : destroy === !1 && (this.set("destroyed", !1), clearTimeout(this.destroying)), !!this.get("destroyed")
            },
            close: function (isFocused) {
                this.user && (this.user.chat = null), this.nudge(!1), this.destroyed(!0), this.collection.queuePush(this, isFocused), this.trigger("close")
            },
            destroy: function () {
                this.user && (this.user.chat = null), this.unsubscribe(), this.messages && (this.messages.reset(), this.messages = null), Backbone.Model.prototype.destroy.apply(this, arguments)
            },
            setupMessages: function () {
                if (this.get("messages")) {
                    var messages = this.get("messages");
                    this.messages = new Messages(messages), this.messages.postPush(!0), this.unset("messages", {
                        silent: !0
                    })
                } else this.messages = new Messages;
                this.eventPassthrough(this.messages, "messages:"), this.listenTo(this.messages, "save", function () {
                    this.destroyed(!1), this.save()
                }), this.listenTo(this.messages, "push", this.sendMessage), this.listenTo(this.messages, "add", function () {
                    this.nudge(!1)
                })
            },
            toJSON: function () {
                var json = Backbone.Model.prototype.toJSON.call(this);
                return json.messages = this.messages.toJSON(), json.user = this.user.toJSON(), json.hasTempID = this.hasTempID(), json.id || (json.id = null), json
            },
            getStoredText: function () {
                return this.get("text")
            },
            setStoredText: function (text) {
                this.set("text", text)
            },
            getTitle: function () {
                var count = this.messages.getUnreadCount(),
                    name = this.user.get("name"),
                    title = _.sprintf("%s sent you a message", name);
                return count == this.messages.length && (title = _.sprintf("(%d) New message%s from %s", count, 1 != count ? "s" : "", name)), title
            },
            getFileUploadURL: function () {
                var url = chatUtil.getURL("chat/attachment/");
                return this.hasTempID() || (url += _.sprintf("%s/", this.id)), url
            },
            getAttachment: function () {
                return this.get("attachment")
            },
            setAttachment: function (attachment) {
                this.set("attachment", attachment)
            },
            hasAttachment: function () {
                return !!this.getAttachment()
            },
            nudge: function (shouldNudge) {
                return shouldNudge === !1 || this.messages.length > 1 ? this.unset("nudge") : shouldNudge === !0 && this.set("nudge", !0), !!this.get("nudge")
            },
            pushMessage: function (text) {
                this.messages.pushMessage({
                    me: !0,
                    text: text,
                    attachment: this.getAttachment()
                }, !0), this.setAttachment(null), this.set({
                    text: ""
                }), this.user.isHidden() && this.user.unhideUser()
            },
            sendMessage: function () {
                if (!this.syncing) {
                    var message = this.messages.getUnsynced().shift();
                    if (message) {
                        this.syncing = !0;
                        var url = _.sprintf("chat/%s/reply/", this.id),
                            data = {
                                ajax: !0,
                                body: message.getText()
                            },
                            existingChat = this.user.hasExistingChat();
                        existingChat || (url = _.sprintf("chat/new-message/%s/", this.user.id)), message.has("attachment") && (data.attachment = message.get("attachment").id), util.API.post(chatUtil.getURL(url), {
                            data: data,
                            csrf: !existingChat,
                            success: function (data) {
                                message.set({
                                    id: data.id,
                                    synced: !0
                                }), !existingChat && data.code && (this.updateID(data.code), this.subscribe(), this.user.setChatID(data.code), this.user.addToRoleSection())
                            }.bind(this),
                            error: function () {
                                ++message.retries >= 5 && message.destroy()
                            }.bind(this),
                            complete: function () {
                                this.syncing = !1, this.save(), this.sendMessage()
                            }.bind(this)
                        })
                    }
                }
            },
            waitForID: function (id) {
                var d = new $.Deferred,
                    interval = null;
                return interval = setInterval(function () {
                    this.id == id && (d.resolve(), clearInterval(interval))
                }.bind(this), 100), d
            },
            markAsRead: function (doSync) {
                var messages = this.messages.where({
                    read: !1
                });
                if (0 !== messages.length) {
                    var success = function () {
                        _.each(messages, function (message) {
                            message.set({
                                read: !0
                            }, {
                                silent: !0
                            })
                        }), this.save(), this.trigger("counter.update")
                    }.bind(this);
                    this.isBot() && (doSync = !1), doSync ? util.API.post(chatUtil.getURL("chat/mark-as-read/"), {
                        data: {
                            ids: _.pluck(messages, "id")
                        },
                        success: success
                    }) : success()
                }
            },
            loadHistory: function () {
                return this.user.hasExistingChat() ? util.API.get(chatUtil.getURL("chat/history/") + this.id + "/", {
                    success: function (data) {
                        data.messages && this.messages.synchronize(data.messages)
                    }.bind(this)
                }) : (new $.Deferred).resolve()
            }
        }),
        ChatCollection = baseModels.AsyncCollection.extend({
            fetch: function () {
                baseModels.AsyncCollection.prototype.fetch.apply(this, arguments), this.on("add", this.addToCollection.bind(this)), this.on("remove", this.removeFromCollection.bind(this))
            },
            addToCollection: function (model) {
                model.save()
            },
            removeFromCollection: function (model) {
                this.sync("delete", model, {})
            },
            _sortByActivity: function () {
                return this.sortBy(function (chat) {
                    return chat.getLastActivity()
                })
            },
            getLeastActive: function () {
                return _.first(this._sortByActivity())
            },
            getLeastActiveRead: function () {
                var chats = this._sortByActivity();
                return _.first(_.filter(chats, function (chat) {
                    return !chat.hasUnreadMessages()
                }))
            },
            checkDestroyed: function () {
                _.each(this.where({
                    destroyed: !0
                }), function (model) {
                    model.destroy()
                })
            }
        }),
        ChatQueue = ChatCollection.extend({
            MAX_QUEUE_SIZE: 5,
            model: Chat,
            asyncStorage: new Backbone.AsyncStorage("ChatQueue"),
            fetch: function () {
                ChatCollection.prototype.fetch.call(this, {
                    notify: !0
                }), this.progress(this.checkDestroyed.bind(this)), this.on("add", this.onAdd.bind(this))
            },
            onAdd: function () {
                if (this.models.length > this.MAX_QUEUE_SIZE) {
                    var model = this.getLeastActiveRead();
                    model && model.destroy()
                }
            },
            getLast: function () {
                return _.last(this.where({
                    destroyed: !1
                }))
            }
        }),
        Chats = ChatCollection.extend({
            model: Chat,
            asyncStorage: new Backbone.AsyncStorage("Chats"),
            initialize: function () {
                this.queue = new ChatQueue, this.on("add", function (model) {
                    model.setDateActive(new Date)
                }), ChatCollection.prototype.initialize.call(this)
            },
            addToCollection: function (model) {
                ChatCollection.prototype.addToCollection.apply(this, arguments), model.destroyed(!1)
            },
            fetch: function () {
                this.queue.fetch(), ChatCollection.prototype.fetch.call(this, {
                    notify: !0
                }), this.checkDestroyed()
            },
            synchronize: function () {
                var self = this;
                return users.Cache.currentUser.isAuthenticated() ? this.progress(function () {
                    util.API.post(chatUtil.getURL("chat/sync/"), {
                        csrf: !0,
                        success: function (data) {
                            data.chats && _.each(data.chats, function (chat, chatID) {
                                var model = self.getChat(chatID),
                                    user = users.Cache.getUser(chat.user);
                                user.collection || user.addToRoleSection(), user.updateAvailability(chat.user), model ? chat.messages && model.messages.synchronize(chat.messages) : (model = new Chat({
                                    id: chatID,
                                    messages: chat.messages || []
                                }), model.setUser(user), self.push(model))
                            })
                        },
                        error: function () {}
                    }).done(function () {
                        self.resolve()
                    })
                }) : this.resolve()
            },
            newMessage: function (data) {
                var model = this.get(data.id),
                    d = (new $.Deferred).resolve(),
                    cb = function () {},
                    self = this,
                    loadHistory = !1,
                    user = users.Cache.getUser(data.user);
                model || (model = this.queue.get(data.id), model ? cb = function () {
                    model.setupNewMessageSound().resolve(), self.queuePop(model, !0)
                } : user.chat ? (model = user.chat, d = model.waitForID(data.id)) : (model = new Chat({
                    id: data.id,
                    minimized: data.minimized
                }), loadHistory = !0, cb = function () {
                    model.newMessageSound.resolve(), self.push(model)
                })), model.setUser(user), user.updateAvailability(data.user), loadHistory && (d = model.loadHistory()), d.always(function () {
                    var message = model.messages.pushMessage(data.message);
                    message.isMe() || user.hasResponded(!0), user.addToRoleSection(), data.nudge && model.nudge(data.nudge), cb()
                })
            },
            newBotMessage: function (data, name) {
                var user = users.Cache.getBot(name),
                    chatID = user.getChatID(),
                    model = this.get(chatID);
                model || (model = this.queue.get(chatID), model ? (model.setupNewMessageSound().resolve(), this.queuePop(model, !0)) : (model = new Chat({
                    id: chatID,
                    minimized: !1
                }), model.setUser(user), model.setupNewMessageSound().resolve(), this.push(model))), model.messages.pushMessage(data.message)
            },
            unqueueChat: function (count) {
                count = count || 1;
                for (var i = 0; count > i; i++) this.queuePop(this.queue.getLast(), !1)
            },
            queueChat: function (count, byActivity) {
                count = count || 1;
                for (var i = 0; count > i; i++) {
                    var chat = byActivity ? this.getLeastActive() : this.last();
                    this.queuePush(chat)
                }
            },
            queuePush: function (chat, isFocused) {
                if (chat) {
                    var index = this.indexOf(chat);
                    this.remove(chat), this.queue.push(chat), this.trigger("queue.push", index, isFocused)
                }
            },
            queuePop: function (chat, unshift) {
                chat && (this.queue.remove(chat), this[unshift ? "unshift" : "push"](chat), this.trigger("queue.pop"))
            },
            pushChat: function (chat, onNew) {
                this._addChat(chat, this.push.bind(this), onNew)
            },
            unshiftChat: function (chat, onNew) {
                this._addChat(chat, this.unshift.bind(this), onNew)
            },
            _addChat: function (chat, addMethod, onNew) {
                if (!this.get(chat)) {
                    var isNew = !0;
                    if (this.queue.get(chat)) {
                        var user = chat.user;
                        this.queue.remove(chat), chat.setUser(user), isNew = !1
                    }
                    addMethod(chat), isNew && _.isFunction(onNew) && onNew()
                }
            },
            getChat: function (id) {
                return this.get(id) || this.queue.get(id)
            },
            getChatByUser: function (user) {
                var userID = _.isObject(user) ? user.id : user;
                return this.findWhere({
                    userID: userID
                }) || this.queue.findWhere({
                    userID: userID
                })
            }
        });
    return {
        Message: Message,
        Messages: Messages,
        Chat: Chat,
        Chats: Chats
    }
}), define("chat/models/util", ["heartbeat", "socket", "config"], function (heartbeat, socket, config) {
    var IdleWatcher = function () {
        var awayCounter = 0,
            CHECK_INTERVAL = 5e3,
            AWAY_THRESHOLD = 9e5,
            AWAY_MAX = AWAY_THRESHOLD / CHECK_INTERVAL,
            reset = function () {
                awayCounter = 0
            },
            isAway = function () {
                return awayCounter == AWAY_MAX
            },
            setActive = function () {
                var _isAway = isAway();
                reset(), _isAway && heartbeat.setAway(!1)
            },
            reportActive = _.throttle(setActive, 1e4),
            reportAway = function () {
                heartbeat.setAway(!0)
            };
        return setInterval(function () {
            document.hasFocus() ? reportActive() : isAway() || (awayCounter++, isAway() && reportAway())
        }, CHECK_INTERVAL), $("html, body").on("mousemove keyup", function () {
            isAway() ? setActive() : reportActive()
        }), {
            reset: reset,
            setMax: function () {
                awayCounter = AWAY_MAX
            }
        }
    };
    return {
        chatSocket: socket.connect("chat"),
        IdleWatcher: IdleWatcher,
        getURL: function (url) {
            return (config.isSSL ? config.BASE_SSL_URL : config.BASE_URL) + url
        }
    }
}), define("chat/models/users", ["base/models", "chat/constants", "chat/models/util", "rollbar", "config", "util"], function (baseModels, constants, chatUtil, rollbar, config, util) {
    var ChatUser = Backbone.NoSync.Model.extend({
            defaults: {
                availableNow: null,
                availability: 0,
                bot: !1,
                chatID: null,
                email: "",
                fromBlast: !1,
                gender: null,
                isBusy: !1,
                name: "",
                photo: "",
                reviews: 0,
                role: 0,
                school: null,
                showInLesson: !1,
                su: !1,
                suMeta: null,
                timezoneOffsetMinutes: null,
                urlID: null,
                lessonLatestSubject: "",
                lessonLatestTime: ""
            },
            meta: ["school", "reviews", "email", "bot", "fromBlast", "showInLesson", "suMeta"],
            initialize: function () {
                this.chat = null, this.forwardsConnection = null, this.backwardsConnection = null, this._hasResponded = !1, this._syncingAvailability = !1, this.autosave(), this.on("change:showInLesson", function (model, show) {
                    !config.LESSON && show && model.unset("showInLesson")
                }), this.get("name") || this.set("name", _.ucfirst(constants.ROLE_STR[this.getRole()]))
            },
            postInit: function () {
                this.createConnections()
            },
            destroy: function () {
                this.chat && this.chat.destroy(), this.chat = null, this.forwardsConnection = null, this.backwardsConnection = null, Backbone.Model.prototype.destroy.apply(this, arguments)
            },
            toJSON: function () {
                var user = Backbone.Model.prototype.toJSON.call(this);
                return _.each(user, function (val, key) {
                    ChatUser.prototype.defaults[key] !== val || _(["id", "name"]).contains(key) || delete user[key]
                }), this.isSuperuser() && (user.photo = UserCache.getSuperuserAvatar()), user
            },
            getChatID: function () {
                return this.get("chatID")
            },
            setChatID: function (chatID) {
                this.set("chatID", chatID), this.chat && this.chat.hasTempID() && this.chat.updateID(chatID)
            },
            getLatestLessonSubject: function () {
                return this.get("lessonLatestSubject")
            },
            setChat: function (chat) {
                this.chat = chat, chat.setUser(this)
            },
            createConnections: function (options) {
                var self = this;
                this.trigger("connections.get", this.id, options, function (forwards, backwards) {
                    self.setForwardsConnection(forwards), self.setBackwardsConnection(backwards), UserCache.currentUser && UserCache.currentUser.isTutor() && (self.set("lessonLatestSubject", forwards.get("lessonLatestSubject")), self.set("lessonLatestTime", forwards.get("lessonLatestTime")))
                })
            },
            resyncAvailability: function () {
                if (!this._syncingAvailability) {
                    this._syncingAvailability = !0;
                    var user = new baseModels.User({
                        id: this.id
                    });
                    user.fetch().done(function () {
                        this.updateAvailability({
                            availability: user.chatAvailability
                        }), this._syncingAvailability = !1
                    }.bind(this))
                }
            },
            updateAvailability: function (data) {
                var current = this.get("availability");
                current != data.availability && (this.set("availability", data.availability), this.removeAndAdd()), _.isBoolean(data.isBusy) && this.updateBusyState(data.isBusy), _.isBoolean(data.availableNow) && this.updateAvailableNow(data.availableNow)
            },
            updateAvailableNow: function (availableNow) {
                this.isAvailableNow() != availableNow && (this.set("availableNow", !!availableNow), this.removeAndAdd())
            },
            updateBusyState: function (isBusy) {
                this.isBusy() != isBusy && (this.set("isBusy", !!isBusy), this.removeAndAdd())
            },
            addToRoleSection: function () {
                if (this.isSuperuser()) {
                    var typeGroup = ChatUserGroups.getTypeGroup("su");
                    return typeGroup ? typeGroup.users.add(this) : ChatUserGroups.addToWaitlist(this), void 0
                }
                var isBlast = this.isBlastUser();
                if (isBlast && this.chat && (isBlast = !this.chat.otherUserHasTalked()), (!this.collection || this.isSubjectSectionUser()) && !isBlast) {
                    this.collection && this.collection.remove(this), this.deleteMeta();
                    var roleGroup = ChatUserGroups.getRoleGroup(this.getRole());
                    roleGroup ? roleGroup.users.add(this) : ChatUserGroups.addToWaitlist(this)
                }
            },
            deleteMeta: function () {
                _.each(this.meta, function (meta) {
                    config.LESSON && "showInLesson" == meta || this.set(meta, this.defaults[meta])
                }.bind(this))
            },
            hasExistingChat: function () {
                return !!this.get("chatID")
            },
            showInLesson: function () {
                return !!this.get("showInLesson")
            },
            isAuthenticated: function () {
                return 0 !== this.id
            },
            isSuperuser: function () {
                return !!this.get("su")
            },
            isBot: function () {
                return !!this.get("bot")
            },
            isSubjectSectionUser: function () {
                return !(!this.collection || !this.collection.group.isSubjectSection())
            },
            isBlastUser: function () {
                return !!this.get("fromBlast")
            },
            isTutor: function () {
                return this.getRole() == constants.ROLE.TUTOR
            },
            isStudent: function () {
                return this.getRole() == constants.ROLE.STUDENT
            },
            isParent: function () {
                return this.getRole() == constants.ROLE.PARENT
            },
            hasSUMeta: function () {
                return !!this.get("suMeta")
            },
            hasStudentEmail: function () {
                return !(!this.isParent() || !this.get("suMeta").childrenEmail)
            },
            hasParentEmail: function () {
                return !(!this.isStudent() || !this.get("suMeta").parentEmail)
            },
            getEmailCount: function () {
                var count = 0;
                return this.hasStudentEmail() && (count += this.get("suMeta").childrenEmail.split(",").length), this.hasParentEmail() && (count += 1), count
            },
            isStudentOrParent: function () {
                return (this.isStudent() || this.isParent()) && !this.isSuperuser()
            },
            isOnline: function () {
                return this.get("availability") == constants.AVAILABILITY.ONLINE
            },
            isAway: function () {
                return this.get("availability") == constants.AVAILABILITY.AWAY
            },
            isOffline: function () {
                return this.get("availability") == constants.AVAILABILITY.OFFLINE
            },
            isBusy: function () {
                return !!this.get("isBusy")
            },
            isAvailableNow: function () {
                return this.isTutor() && this.get("availableNow")
            },
            isHidden: function () {
                return this.forwardsConnection && this.forwardsConnection.isHidden()
            },
            isHidingMe: function () {
                return this.backwardsConnection && this.backwardsConnection.isHidden()
            },
            isBlocked: function () {
                return this.forwardsConnection && this.forwardsConnection.isBlocked()
            },
            isBlockingMe: function () {
                return this.backwardsConnection && this.backwardsConnection.isBlocked()
            },
            isNormal: function () {
                return this.forwardsConnection && this.forwardsConnection.isNormal()
            },
            isCoolWithMe: function () {
                return this.backwardsConnection && this.backwardsConnection.isNormal()
            },
            getName: function () {
                return this.get("name")
            },
            getUniqueNameURL: function () {
                return this.get("urlID")
            },
            getRole: function () {
                return this.get("role")
            },
            getFirstName: function () {
                return this.getName().split(" ").shift()
            },
            getGender: function () {
                return this.get("gender")
            },
            setForwardsConnection: function (connection) {
                this.listenTo(connection, "change", function () {
                    this.trigger("change:forwardsConnection")
                }), this.forwardsConnection = connection, connection.trigger("change")
            },
            setBackwardsConnection: function (connection) {
                this.listenTo(connection, "change", function () {
                    this.trigger("change:backwardsConnection")
                }), this.backwardsConnection = connection, connection.trigger("change")
            },
            toggleBlocked: function () {
                this.forwardsConnection.isBlocked() ? this.forwardsConnection.setNormal().save() : this.forwardsConnection.setBlocked().save()
            },
            hideUser: function () {
                this.forwardsConnection.setHidden().save()
            },
            unhideUser: function () {
                this.forwardsConnection.setNormal().save()
            },
            hasResponded: function (responded) {
                return _.isUndefined(responded) || (this._hasResponded = !!responded, this.trigger("change:hasResponded", responded)), this._hasResponded
            },
            canMeetNow: function () {
                return this.isAvailableNow() ? !0 : this.chat ? this.isOnline() && !this.isBusy() && this.hasResponded() : !1
            }
        }),
        ChatUserCollection = Backbone.Collection.extend({
            model: ChatUser
        }),
        ChatUsers = ChatUserCollection.extend({
            comparator: function (m1, m2) {
                var m1a = m1.get("availability"),
                    m2a = m2.get("availability"),
                    m1an = m1.isAvailableNow(),
                    m2an = m2.isAvailableNow(),
                    m1b = m1.isBusy(),
                    m2b = m2.isBusy(),
                    m1n = (m1.get("name") || "").toLowerCase(),
                    m2n = (m2.get("name") || "").toLowerCase();
                return m1b && (m1a = constants.AVAILABILITY.OFFLINE + .5), m2b && (m2a = constants.AVAILABILITY.OFFLINE + .5), m1an && (m1a = constants.AVAILABILITY.ONLINE + .5), m2an && (m2a = constants.AVAILABILITY.ONLINE + .5), m1a > m2a ? -1 : m1a == m2a ? m1n == m2n ? 0 : m2n > m1n ? -1 : 1 : 1
            },
            initialize: function () {
                this.group = null, this.on("change:availability", this.sort.bind(this))
            }
        }),
        SubjectSectionChatUsers = ChatUsers.extend({
            comparator: "cid"
        }),
        UserCache = new(ChatUserCollection.extend({
            currentUser: null,
            initialize: function () {
                util.makeDeferred(this), ChatUserCollection.prototype.initialize.apply(this, arguments)
            },
            _getUser: function (user) {
                if (user instanceof this.model) return user;
                var model = this.get(user);
                return _.isObject(user) && (model ? model.set(user) : (model = new this.model(user), model.on("destroy", function () {
                    this.remove(model), this.stopListening(model)
                }.bind(this)), this.add(model), this.listenTo(model, "all", function () {
                    this.trigger.apply(this, arguments)
                }), model.postInit(), model.collection = null)), model
            },
            getUser: function (user, callback) {
                return _.isFunction(callback) ? this.done(function () {
                    callback(this._getUser(user))
                }.bind(this)) : this._getUser(user)
            },
            _getUsers: function (users) {
                return _.map(users, function (user) {
                    return this.getUser(user)
                }.bind(this))
            },
            getUsers: function (users, callback) {
                return _.isFunction(callback) ? this.done(function () {
                    callback(this._getUsers(users))
                }.bind(this)) : this._getUsers(users)
            },
            getUserInfo: function (uid) {
                var self = this,
                    finished = new $.Deferred,
                    endpoint = _.sprintf("chat/get-user-info/%s/", uid),
                    user = this.getUser(uid);
                return user ? finished.resolve(user) : util.API.get(chatUtil.getURL(endpoint), {
                    success: function (data) {
                        user = self.getUser(data.user), finished.resolve(user)
                    }
                }), finished
            }
        })),
        ChatUserGroup = Backbone.Model.extend({
            defaults: {
                name: "",
                url: "",
                role: 0,
                subjectID: 0,
                type: "",
                showLastLesson: !1
            },
            initialize: function () {
                this.setupUsers(), this.autosave([
                    [this.users, "change"],
                    [this.users, "add"],
                    [this.users, "remove"]
                ])
            },
            sync: function () {
                return this.collection ? Backbone.Model.prototype.sync.apply(this, arguments) : !0
            },
            destroy: function () {
                this.resetUsers(), Backbone.Model.prototype.destroy.apply(this, arguments)
            },
            getRole: function () {
                return this.get("role")
            },
            getType: function () {
                return this.get("type")
            },
            resetUsers: function () {
                this.users.reset()
            },
            setUsers: function (users) {
                users && (users = UserCache.getUsers(users), _.each(users, function (user) {
                    user.collection && user.collection != this.users && user.collection.remove(user, {
                        manual: !0
                    }), this.isSubjectSection() || user.deleteMeta()
                }.bind(this)), this.users.set(users, {
                    loading: !0
                }))
            },
            isSubjectSection: function () {
                return !!this.get("subjectID")
            },
            isSuperuser: function () {
                return "su" == this.getType()
            },
            showInLesson: function () {
                return this.users.where({
                    showInLesson: !0
                }).length > 0
            },
            checkAvailability: function (model) {
                model.isOffline() && this.isSubjectSection() && !model.chat && this.getNewUser({
                    model: model
                })
            },
            userRemoved: function (model, collection, options) {
                this.isSubjectSection() && !options.manual && this.getNewUser({
                    model: model
                })
            },
            getNewUser: function (options) {
                var url = _.sprintf("chat/new-user/%s/", this.get("subjectID")),
                    uids = _.compact(UserCache.pluck("id"));
                util.API.post(chatUtil.getURL(url), {
                    data: {
                        uids: JSON.stringify(uids),
                        count: options.count || 1
                    },
                    csrf: !0,
                    success: function (data) {
                        data.users && (options.model && this.users.contains(options.model) && options.model.destroy({
                            manual: !0
                        }), _.each(data.users, function (user) {
                            this.users.add(UserCache.getUser(user))
                        }.bind(this)))
                    }.bind(this),
                    complete: function (data) {
                        _.isFunction(options.complete) && options.complete(data)
                    }
                })
            },
            getUsersClass: function () {
                return this.isSubjectSection() ? new SubjectSectionChatUsers : new ChatUsers
            },
            setupUsers: function () {
                this.users = this.getUsersClass(), this.users.group = this, this.get("users") && (this.users.add(UserCache.getUsers(this.get("users"))), this.unset("users", {
                    silent: !0
                })), this.users.on("change:availability", this.checkAvailability.bind(this)), this.users.on("remove", this.userRemoved.bind(this)), this.eventPassthrough(this.users, "users:")
            },
            toJSON: function () {
                var json = Backbone.Model.prototype.toJSON.call(this);
                return json.users = this.users.toJSON(), json.isSubjectSection = this.isSubjectSection(), json.isSuperuser = this.isSuperuser(), json
            }
        }),
        ChatUserGroups = baseModels.AsyncCollection.extend({
            model: ChatUserGroup,
            asyncStorage: new Backbone.AsyncStorage("ChatUserGroups"),
            comparator: "id",
            initialize: function () {
                baseModels.AsyncCollection.prototype.initialize.call(this), this.on("add", this.addGroup.bind(this))
            },
            fetch: function () {
                baseModels.AsyncCollection.prototype.fetch.call(this, {
                    notify: !0
                })
            },
            loadGroups: function (groups) {
                var self = this;
                _.each(groups, function (group, key) {
                    var model = self.get(key);
                    model && model.get("name") != group.name && (model.destroy(), model = null), model || (model = new self.model({
                        id: key,
                        name: group.name,
                        subjectID: group.subjectID,
                        role: group.role,
                        type: group.type || "",
                        showLastLesson: !!group.showLastLesson && !_.isEmpty(group.users) && config.addLessonsMetaOnOmnibar
                    })), model.setUsers(group.users), model.save(), self.add(model, {
                        at: key
                    })
                }), self.sort()
            },
            addGroup: function (group) {
                var groupType = group.getType();
                groupType && (ChatUserGroups.types[groupType] = group);
                var groupRole = group.getRole();
                groupRole && (ChatUserGroups.roles[groupRole] = group), _.each(ChatUserGroups.waitlist, function (user, id) {
                    user.isSuperuser() ? group.isSuperuser() && (group.users.add(user), delete ChatUserGroups.waitlist[id]) : user.getRole() == groupRole && (group.users.add(user), delete ChatUserGroups.waitlist[id])
                })
            },
            fromGroups: function () {
                var groups = [];
                return _.each(this.models, function (model) {
                    groups.push({
                        name: model.get("name"),
                        users: model.users.pluck("id"),
                        subjectID: model.get("subjectID")
                    })
                }), groups
            },
            synchronize: function () {
                var self = this;
                return this.progress(function () {
                    UserCache.currentUser.isTutor() && self.removeSubjectSections(), util.API.post(chatUtil.getURL("chat/omnibar-sync/"), {
                        csrf: !0,
                        data: {
                            groups: JSON.stringify(self.fromGroups())
                        },
                        success: function (data) {
                            data.groups && self.loadGroups(data.groups)
                        },
                        error: function (_, xhr, textStatus) {
                            "abort" != textStatus && rollbar.log("omnibar-sync failed")
                        }
                    }).done(function () {
                        self.resolve()
                    })
                })
            },
            removeSubjectSections: function () {
                this.destroyMulti(function (group) {
                    return group.isSubjectSection()
                })
            }
        });
    return _.extend(ChatUserGroups, {
        roles: {},
        types: {},
        waitlist: {},
        addToWaitlist: function (user) {
            ChatUserGroups.waitlist[user.id] = user
        },
        getRoleGroup: function (role) {
            return ChatUserGroups.roles[role]
        },
        getTypeGroup: function (type) {
            return ChatUserGroups.types[type]
        }
    }), {
        ChatUser: ChatUser,
        ChatUsers: ChatUsers,
        ChatUserGroup: ChatUserGroup,
        ChatUserGroups: ChatUserGroups,
        Cache: UserCache
    }
}), define("chat/support/models", ["chat/constants", "chat/models", "chat/models/users", "chat/models/util", "base/models", "socket", "util"], function (constants, models, users, chatUtil, baseModels, socket, util) {
    var doNothing = function () {},
        SupportChatUser = users.ChatUser.extend({
            deleteMeta: doNothing,
            removeAndAdd: doNothing,
            postInit: function () {
                this.get("forwards") && this.createConnections({
                    forwards: this.get("forwards"),
                    backwards: this.get("backwards")
                })
            },
            addToRoleSection: function () {
                if (this.isSuperuser()) {
                    var typeGroup = models.ChatUserGroups.getTypeGroup("su");
                    typeGroup.users.add(this)
                } else {
                    var roleGroup = models.ChatUserGroups.getRoleGroup(this.getRole());
                    roleGroup.users.add(this)
                }
            },
            setForwardsConnection: function (connection) {
                this.listenTo(connection, "change", function () {
                    this.set("forwards", connection.toJSON())
                }.bind(this)), users.ChatUser.prototype.setForwardsConnection.apply(this, arguments)
            },
            setBackwardsConnection: function (connection) {
                this.listenTo(connection, "change", function () {
                    this.set("backwards", connection.toJSON())
                }.bind(this)), users.ChatUser.prototype.setBackwardsConnection.apply(this, arguments)
            },
            fetchSUMetadata: function () {
                if (this.hasSUMeta()) return (new $.Deferred).resolve();
                var url = _.sprintf("chat/get-su-metadata/%s/", this.id),
                    self = this;
                return util.API.get(chatUtil.getURL(url)).done(function (data) {
                    self.set("suMeta", data.suMeta), self.createConnections(data.connections), data.conversationCode && (self.setChatID(data.conversationCode), self.chat && (self.chat.updateID(data.conversationCode), self.chat.loadHistory()))
                })
            }
        }),
        SupportChatUsers = models.ChatUsers.extend({
            model: SupportChatUser,
            getUsersLike: function (val) {
                return val.indexOf("@") > -1 ? this.like({
                    email: val
                }) : this.like({
                    name: val
                })
            }
        }),
        SupportChatUserGroup = models.ChatUserGroup.extend({
            checkAvailability: doNothing,
            getUsersClass: function () {
                return new SupportChatUsers
            }
        }),
        SupportChatUserGroups = models.ChatUserGroups.extend({
            model: SupportChatUserGroup,
            synchronize: function () {
                return this.progress(function () {
                    this.removeSubjectSections(), this.loadGroups([{
                        name: "Support",
                        type: "su"
                    }, {
                        name: "Tutors",
                        role: constants.ROLE.TUTOR
                    }, {
                        name: "Students",
                        role: constants.ROLE.STUDENT
                    }, {
                        name: "Parents",
                        role: constants.ROLE.PARENT
                    }]), this.resolve()
                }.bind(this))
            }
        }),
        SupportInlineChat = models.InlineChat.extend({
            setupSocket: function () {
                var availabilityEvents = {
                    "chat:update.availability": this.updateAvailability.bind(this)
                };
                users.Cache.on("add", function (user) {
                    var roomKey = "presence=" + user.id;
                    socket.subscribe(roomKey, availabilityEvents), user.on("destroy", function () {
                        socket.unsubscribe(roomKey)
                    })
                });
                var userEvents = {
                    "chat:new.message": this.chats.newMessage.bind(this.chats),
                    "connection:update": this.updateConnection.bind(this),
                    signedout: this.signOut.bind(this)
                };
                socket.subscribe("user=" + this.user.get("userID"), userEvents)
            },
            onProgress: function () {
                this.progress(function () {
                    this.groups.fetch(), this.chats.fetch(), this.connections.resolve()
                }.bind(this))
            }
        });
    return users.Cache.model = SupportChatUser, models.CLASSES.ChatUserGroups = SupportChatUserGroups, _.extend(models, {
        InlineChat: SupportInlineChat
    })
}), define("chat/support/views", ["chat/constants", "chat/views", "chat/view-utils", "chat/support/models", "chat/models/users", "util"], function (constants, views, viewUtils, supportModels, users, util) {
    var doNothing = function () {},
        SupportChatItem = views.ChatItem.extend({
            ui: {
                userSUMeta: ".user-su-meta"
            },
            initialize: function () {
                views.ChatItem.prototype.initialize.apply(this, arguments), this._chatSUMeta = Backbone.Marionette.TemplateCache.get("#chat-su-meta-template")
            },
            onRender: function () {
                views.ChatItem.prototype.onRender.apply(this, arguments), this.model.user.isSuperuser() && this.$el.addClass("chat-support"), this.model.user.fetchSUMetadata().done(function () {
                    var json = viewUtils.getUserJSON(this.model.user);
                    this.ui.userSUMeta.replaceWith(this._chatSUMeta({
                        user: json
                    })), this.ui.container.addClass("chat-container-admin"), this.$('[rel="tooltip"]').tooltip(), this.adjustConversationHeight()
                }.bind(this))
            },
            _getHeightAdjustment: function () {
                var height = views.ChatItem.prototype._getHeightAdjustment.apply(this, arguments);
                return height -= 3, this.model.user.hasSUMeta() && (this.model.user.hasStudentEmail() || this.model.user.hasParentEmail()) && (height -= 20 * this.model.user.getEmailCount(), this.ui.moreDropdown.addClass("two-emails")), height
            }
        }),
        SupportChatUser = views.ChatUser.extend({
            fadeIn: function () {
                this.show()
            },
            hide: function () {
                this.el.style.display = "none"
            },
            show: function () {
                this.el.style.display = "list-item"
            },
            destroy: function () {
                this.close()
            }
        }),
        SupportChatUserGroup = Backbone.Marionette.CollectionView.extend({
            itemView: SupportChatUser,
            collectionEvents: {
                sort: "render",
                "search:results": "showSearchResults"
            },
            showSearchResults: function (users) {
                this.el.style.display = "none", this.children.call("hide"), _.each(users, function (user) {
                    var view = this.children.findByModel(user);
                    view && view.show()
                }.bind(this)), this.el.style.display = "block"
            }
        }),
        SupportOmnibar = views.Omnibar.extend({
            events: {
                'keyup .chat-header input[type="text"]': "searchUsers",
                "click .chat-header .icon-search": "searchUsersAJAX"
            },
            render: function () {
                var suOmnibarHeader = Backbone.Marionette.TemplateCache.get("#omnibar-superuser-header");
                this.ui.chatName.text("").append(suOmnibarHeader()), this.bindUIElements();
                var self = this;
                this.typeahead = _.debounce(function (query, success) {
                    self.startSpinner(), util.API.get("chat/search-users/", {
                        data: {
                            query: query
                        },
                        checkDataForDoubleSubmit: !0,
                        success: success,
                        complete: function () {
                            self.stopSpinner()
                        }
                    })
                }, 500), views.Omnibar.prototype.render.call(this)
            },
            getSpinnerOptions: function () {
                var options = views.Omnibar.prototype.getSpinnerOptions.call(this);
                return options.left = 165, options
            },
            _showSearchUsers: function (val) {
                this.groups.collection.each(function (group) {
                    if (val && val.length >= 3) {
                        var users = group.users.getUsersLike(val);
                        group.users.trigger("search:results", users)
                    } else group.users.trigger("search:results", group.users.models)
                })
            },
            searchUsers: function (event) {
                var val = this.ui.input.val();
                return util.isEnterKey(event) ? (this.searchUsersAJAX(), !1) : (this._showSearchUsers(val), !0)
            },
            searchUsersAJAX: function () {
                var val = this.ui.input.val(),
                    self = this;
                return this.groups.collection.each(function (group) {
                    group.trigger("hide"), group.users.destroyMulti(function (model) {
                        return !model.chat
                    })
                }), _.isBlank(val) ? !1 : (this.typeahead(val, function (data) {
                    self.addSearchUsers(data.users), self._showSearchUsers(val), self.ui.body.scrollTop(0)
                }), !0)
            },
            addSearchUsers: function (searchUsers) {
                var models = users.Cache.getUsers(searchUsers),
                    superusers = [],
                    roles = {};
                if (roles[constants.ROLE.TUTOR] = [], roles[constants.ROLE.STUDENT] = [], roles[constants.ROLE.PARENT] = [], _(models).each(function (user) {
                    user.isSuperuser() ? superusers.push(user) : roles[user.getRole()].push(user)
                }), _(roles).each(function (users, role) {
                    var roleGroup = supportModels.ChatUserGroups.getRoleGroup(role);
                    roleGroup.users.add(users)
                }), superusers.length > 0) {
                    var supportGroup = supportModels.ChatUserGroups.getTypeGroup("su");
                    supportGroup.users.add(superusers)
                }
            }
        }),
        SupportChatGroup = views.ChatGroup.extend({
            ui: {
                userCount: ".js-user-count"
            },
            modelEvents: {
                "users:add users:remove": "updateCount"
            },
            getUserGroupClass: function () {
                return SupportChatUserGroup
            },
            show: function () {
                this.ui.userList.show()
            },
            hide: function () {
                this.ui.userList.hide()
            },
            updateCount: function () {
                this.ui.userCount.text(this.model.users.length)
            },
            serializeData: function () {
                var json = views.ChatGroup.prototype.serializeData.apply(this, arguments);
                return json.userCount = this.model.users.length, json
            },
            checkUsers: doNothing,
            checkEmpty: doNothing
        }),
        SupportOmnibarGroups = views.OmnibarGroups.extend({
            itemView: SupportChatGroup
        }),
        SupportChatWindows = views.ChatWindows.extend({
            getItemView: function (model) {
                return model.isBot() ? views.BotItem : SupportChatItem
            }
        });
    return views.CLASSES.InlineChat = supportModels.InlineChat, views.CLASSES.Omnibar = SupportOmnibar, views.CLASSES.ChatWindows = SupportChatWindows, views.CLASSES.OmnibarGroups = SupportOmnibarGroups, {
        init: views.init
    }
}), define("schedule/models", ["util"], function (util) {
    var ENDPOINTS = {
            inbox: "schedule/",
            "view-proposal": "schedule/proposals/view/%s/",
            "cancel-proposal": "schedule/proposals/%s/cancel/",
            "counter-proposal": "schedule/proposals/counter/%s/",
            "confirm-proposal": "schedule/confirm/%s/",
            "create-proposal": "schedule/proposals/create/",
            "create-proposal-user": "schedule/proposals/create/%s/",
            "decline-proposal": "schedule/reject/%s/",
            "reschedule-proposal": "schedule/reschedule/%s/",
            "validate-proposal": "schedule/proposals/validate/",
            "mark-as-read": "schedule/proposals/%s/mark-as-read/",
            "cancel-partial-series": "schedule/proposals/%s/cancel-partial-series/",
            "cancel-lesson-series": "schedule/proposals/%s/cancel-lesson-series/",
            "cancel-lesson": "schedule/proposals/%s/cancel-lesson/"
        },
        Proposal = util.BaseModel.extend({
            id: null,
            getOptions: function (options, csrf) {
                return options = options || {}, csrf && (options.csrf = !0), options
            },
            create: function (options) {
                util.API.post(ENDPOINTS["create-proposal"], this.getOptions(options))
            },
            counter: function (options) {
                util.API.post(_.sprintf(ENDPOINTS["counter-proposal"], this.id), this.getOptions(options))
            },
            reschedule: function () {},
            cancel: function (options) {
                util.API.post(_.sprintf(ENDPOINTS["cancel-proposal"], this.id), this.getOptions(options, !0))
            },
            confirm: function (options) {
                util.API.post(_.sprintf(ENDPOINTS["confirm-proposal"], this.id), this.getOptions(options, !0))
            },
            decline: function (options) {
                util.API.post(_.sprintf(ENDPOINTS["decline-proposal"], this.id), this.getOptions(options, !0))
            },
            validate_: function (options) {
                util.API.post(_.sprintf(ENDPOINTS["validate-proposal"], this.id), this.getOptions(options, !0))
            },
            markAsRead: function () {
                util.API.post(_.sprintf(ENDPOINTS["mark-as-read"], this.id), this.getOptions({})), this.destroy()
            },
            viewCreate: function (options, user) {
                var endpoint = ENDPOINTS["create-proposal"];
                user && (endpoint = _.sprintf(ENDPOINTS["create-proposal-user"], user)), util.API.get(endpoint, this.getOptions(options))
            },
            viewRespond: function (options) {
                util.API.get(_.sprintf(ENDPOINTS["view-proposal"], this.id), this.getOptions(options))
            },
            viewCancel: function (options) {
                util.API.get(_.sprintf(ENDPOINTS["cancel-proposal"], this.id), this.getOptions(options))
            },
            viewCounter: function (options) {
                util.API.get(_.sprintf(ENDPOINTS["counter-proposal"], this.id), this.getOptions(options))
            },
            viewReschedule: function () {}
        }),
        ProposalCollection = Backbone.Collection.extend({
            model: Proposal
        }),
        Lesson = util.BaseModel.extend({
            id: null,
            proposalID: null,
            initialize: function (options) {
                this.proposalID = options.proposalID, this.seriesID = options.seriesID
            },
            viewReschedule: function (options) {
                util.API.get(_.sprintf(ENDPOINTS["reschedule-proposal"], this.id), options)
            },
            reschedule: function (options) {
                util.API.post(_.sprintf(ENDPOINTS["reschedule-proposal"], this.id), options)
            },
            viewCancelLesson: function (options) {
                util.API.get(_.sprintf(ENDPOINTS["cancel-lesson"], this.id), options)
            },
            cancelLesson: function (options) {
                util.API.post(_.sprintf(ENDPOINTS["cancel-lesson"], this.id), options)
            },
            viewCancelLessonSeries: function (options) {
                return util.API.get(_.sprintf(ENDPOINTS["cancel-lesson-series"], this.id), options)
            },
            cancelPartialSeries: function (options) {
                return util.API.post(_.sprintf(ENDPOINTS["cancel-partial-series"], this.id), options)
            },
            cancelLessonSeries: function (options) {
                return util.API.post(_.sprintf(ENDPOINTS["cancel-lesson-series"], this.id), options)
            }
        }),
        LessonCollection = Backbone.Collection.extend({
            model: Lesson,
            destroyLessons: function (lessonIDs) {
                _.each(lessonIDs, function (id) {
                    var model = this.get(String(id));
                    model && model.destroy()
                }.bind(this))
            }
        });
    return {
        ENDPOINTS: ENDPOINTS,
        Proposal: Proposal,
        ProposalCollection: ProposalCollection,
        Lesson: Lesson,
        LessonCollection: LessonCollection
    }
}), define("schedule/meet-now", ["chat/models/users", "chat/view-utils", "base/views", "base/notifications", "schedule/views", "schedule/models", "events", "config", "socket", "util"], function (users, chatUtils, baseViews, notifications, views, models, events, config, socket, util) {
    var signupModal;
    config.isAuthenticated || (signupModal = baseViews.SignUpModal("js-meet-now-carrot", {
        onShow: function (userName, $modal, $carrot) {
            window.mixpanelTrack("Sign Up Modal shown");
            var $role = $modal.find(".form-group-user-role").hide();
            $role.find(":input").first().prop("checked", !0), $carrot.find(".user-name").text(userName);
            var $run = $modal.find("[name=redirect-url-name]"),
                redirect = $run.val();
            $run.attr("old-redirect-url-name", redirect).val("")
        },
        onHide: function ($modal) {
            var $run = $modal.find("[name=redirect-url-name]");
            $run.val($run.attr("old-redirect-url-name")), $modal.find(".form-group-user-role").show()
        },
        onSuccess: function (data) {
            window.location.href = data.nextURL
        }
    }));
    var MeetNowProposalModalView = views.ProposalModalView.extend({
            _super: views.ProposalModalView.prototype,
            initialize: function () {
                this._super.initialize.apply(this, arguments), this.$el.on("hide", function () {
                    notifications.removeTabTitle(this)
                }.bind(this))
            },
            getTitle: function () {
                return "New lesson!"
            },
            _getModal: function () {
                return this.$el.modal({
                    backdrop: "static"
                })
            },
            showProposalSuccess: function () {
                this._super.showProposalSuccess.apply(this, arguments), document.hasFocus() || chatUtils.playChatSound(), notifications.addTabTitle(this)
            },
            declineProposal: function () {
                notifications.removeTabTitle(this), this._super.declineProposal.apply(this, arguments)
            },
            declineSuccess: function (data) {
                this._super.declineSuccess.apply(this, arguments), users.Cache.currentUser.isTutor() && data.otherUser && users.Cache.getUserInfo(data.otherUser).done(function (user) {
                    var $meetNowDeclinedModal = $("#meet-now-declined-tutor").find(".user-name").text(user.getFirstName()).end().modal("show");
                    setTimeout(function () {
                        $meetNowDeclinedModal.modal("hide")
                    }, 5e3), $meetNowDeclinedModal.on("hidden", function () {
                        user.chat && user.chat.trigger("focus"), $meetNowDeclinedModal.off("hidden")
                    }), Backbone.trigger("chat:open", user)
                })
            },
            confirmProposal: function (event) {
                notifications.removeTabTitle(this), this._super.confirmProposal.call(this, event)
            }
        }),
        MeetNowProposal = function () {
            this.model = new models.Proposal, this.$notAvailableModal = $("#meet-now-not-available"), this.$notAvailableModal.on("click", ".cta-blue", function () {
                window.location.reload()
            })
        };
    _.extend(MeetNowProposal.prototype, Backbone.Events, {
        createProposal: function (userID, userName, subjectID, context, onCreate, onError) {
            var self = this;
            this.model.create({
                csrf: !0,
                data: this.getProposalData(userID, subjectID, context),
                success: function (data) {
                    self.proposalCreated(data, userID, userName, context, onCreate)
                },
                statusCode: {
                    403: function () {
                        self.$notAvailableModal.find(".user-name").text(userName), self.$notAvailableModal.modal("show"), _.isFunction(onError) && onError()
                    }
                }
            })
        },
        proposalCreated: function (data, userID, userName, context, onCreate) {
            _.isFunction(onCreate) && onCreate(data), this._trackProposal(data, context), config.isAuthenticated ? data.redirect ? window.location.href = data.redirect : this.trigger("proposal.created", userID, userName, data.proposalID) : signupModal.show(userName)
        },
        _trackProposal: function (data, context) {
            var trackingData = {
                context: context,
                proposalID: data.proposalID,
                availableNow: data.availableNow
            };
            data.proposalID && events.create(events.EVENT.MEET_NOW_REQUEST_SENT, trackingData), window.mixpanelTrack("Meet Now Request Sent", trackingData)
        },
        cancelProposal: function (proposalID) {
            if (!proposalID) return this.trigger("proposal.canceled"), void 0;
            var self = this;
            this.model.id = proposalID, this.model.cancel({
                csrf: !0,
                success: function () {
                    self.trigger("proposal.canceled")
                },
                complete: function () {
                    self.model.id = null
                }
            })
        },
        getProposalData: function (userID, subjectID, context) {
            var lessonDelayStartMinutes = 3,
                time = util.getMinTime({
                    meetNow: !0
                });
            time.setMinutes(time.getMinutes() + lessonDelayStartMinutes);
            var studentID, tutorID, me = users.Cache.currentUser;
            return me.isTutor() ? (tutorID = me.id, studentID = userID) : (tutorID = userID, studentID = me.id), {
                tutor: tutorID || null,
                student: studentID || null,
                proposer: me.id || null,
                duration: 60,
                subject: subjectID,
                recurring_type: "",
                recurring_days: "",
                note: "",
                scheduled_time: _.sprintf("%02d/%02d/%04d %02d:%02d:00", time.getMonth() + 1, time.getDate(), time.getFullYear(), time.getHours(), time.getMinutes()),
                meetNow: 1,
                encoded: 1,
                context: context
            }
        }
    });
    var SubjectModal = Backbone.Marionette.View.extend({
            ui: {
                button: "button",
                select: "select",
                tutorName: ".tutor-name"
            },
            events: {
                "click @ui.button": "submit"
            },
            initialize: function (options) {
                this.bindUIElements(), this._setupSubjects = options.setupSubjects, this._submit = options.submit
            },
            show: function (tutorID, tutorName, context) {
                this.tutorID = tutorID, this.context = context, this.ui.tutorName.text(tutorName), this._setupSubjects(this.ui.select, this.tutorID, config.uid), this.ui.button.enable(), this.$el.modal("show")
            },
            hide: function () {
                this.$el.modal("hide")
            },
            submit: function () {
                var subjectID = this.ui.select.val(),
                    tutorName = this.ui.tutorName.text();
                _.isBlank(subjectID) || (this.ui.button.disable(), this.hide(), this._submit(this.tutorID, tutorName, subjectID, {
                    context: this.context
                }))
            }
        }),
        MeetNow = function () {
            socket.subscribe("user=" + config.uid, {
                "schedule:new.proposal": this.newProposal.bind(this),
                "schedule:meet-now.converting": this.converting.bind(this),
                "schedule:meet-now.expired": this.expired.bind(this),
                "lesson:meet-now.accepted": this.accepted.bind(this)
            }), this.proposalModal = new MeetNowProposalModalView({
                el: "#chat-proposal",
                prefix: "chat-"
            }), this.meetNowProposal = new MeetNowProposal, this.meetNowProposal.on("proposal.created", this.created.bind(this)), this.meetNowProposal.on("proposal.canceled", this.canceled.bind(this)), this.subjectModal = new SubjectModal({
                el: "#meet-now-subject-modal",
                setupSubjects: this.setupSubjects.bind(this),
                submit: this.submit.bind(this)
            }), this.$sendingModal = $("#meet-now-sending-modal"), this.$whatHappensModal = $("#meet-now-what-happens-modal"), this.enableTimeout = null, this.startTimer()
        };
    return _.extend(MeetNow.prototype, Backbone.Events, {
        getElements: function () {
            return $(".js-meet-now")
        },
        getElementsForUser: function (uid) {
            return this.getElements().filter("[data-uid=" + uid + "]")
        },
        getTooltipElementsForUser: function (uid) {
            return this.getElementsForUser(uid).filter(".js-meet-now-tooltip")
        },
        bindCancel: function ($el) {
            $el.find(".js-meet-now-cancel").on("click", function () {
                this.meetNowProposal.cancelProposal(this.getCurrentMeetNowID())
            }.bind(this))
        },
        updateConfig: function (expireTime, uid, proposalID) {
            config.update({
                meetNowID: proposalID,
                meetNowUser: uid,
                meetNowExpireTime: expireTime
            }), this.resetAll(), expireTime > 0 && this.startTimer()
        },
        getExpireTime: function () {
            return config.meetNowExpireTime || 0
        },
        getCurrentMeetNowUser: function () {
            return config.meetNowUser
        },
        getCurrentMeetNowID: function () {
            return config.meetNowID
        },
        hasPendingRequest: function () {
            return this.getExpireTime() > 0
        },
        hasPendingRequestFor: function (userID) {
            return this.getCurrentMeetNowUser() == userID
        },
        hasOpenProposalModal: function () {
            return this.proposalModal.$el.is(":visible")
        },
        startTimer: function () {
            clearTimeout(this.enableTimeout), this.hasPendingRequest() && (this.enableTimeout = setTimeout(this.updateConfig.bind(this, 0), 1e3 * this.getExpireTime()))
        },
        resetAll: function () {
            var self = this;
            this.getElements().each(function () {
                var $el = $(this),
                    uid = $el.data("uid");
                self.updateButtonsForUser(uid, {
                    $el: $el
                })
            })
        },
        updateButtonsForUser: function (user, options) {
            users.Cache.getUser(user, function (model) {
                model || (model = new users.ChatUser({
                    id: user
                })), this._updateState(model, options)
            }.bind(this))
        },
        _updateState: function (user, options) {
            options = options || {}, options.noResponse = !user.canMeetNow(), options.$el || (options.$el = this.getTooltipElementsForUser(user.id)), options.$el.hasClass("js-meet-now-tooltip") ? this._updateTooltip(user, options) : this._updateButton(user, options)
        },
        _updateTooltip: function (user, options) {
            var $el = options.$el,
                name = user.get("name"),
                tooltip = "";
            this.hasPendingRequest() ? tooltip = "You may only have a single Meet Now proposal active." : user.isBlocked() ? tooltip = "You have blocked " + name : user.isOffline() ? tooltip = name + " is offline. To meet, please schedule a lesson in the future." : user.isAway() ? tooltip = name + " is currently idle. To meet, please schedule a future lesson." : user.isBusy() ? tooltip = name + " is currently busy. To meet, please schedule a future lesson." : options.converting ? tooltip = name + " is currently unable to accept Meet Now proposals." : options.noResponse && (tooltip = "Once " + name + " responds, you'll be able to start a lesson."), _.isBlank(tooltip) ? $el.enable().attr("title", "").tooltip("destroy") : $el.disable().attr("title", tooltip).tooltip("fixTitle")
        },
        _updateButton: function (user, options) {
            var $el = options.$el;
            $el.removeClass("meet-now-pending meet-now-one-request"), this.hasPendingRequest() && (this.hasPendingRequestFor(user.id) ? $el.addClass("meet-now-pending") : $el.addClass("meet-now-one-request"))
        },
        newProposal: function (data) {
            data.meetNow && (data.actionable ? this.received(data) : data.confirmed ? this.confirmed(data) : data.declined && this.canceled(data))
        },
        converting: function (data) {
            this.trigger("converting", data), this.updateButtonsForUser(data.user, data)
        },
        received: function (data) {
            this.trigger("received", data), data.id ? this.proposalModal.setModelByID(data.id) : this.proposalModal.setModel(), this.proposalModal.showProposal(function (options) {
                this.proposalModal.model.viewRespond(options)
            }.bind(this))
        },
        confirmed: function (data) {
            this.trigger("confirmed", data), this.updateConfig(0)
        },
        accepted: function (data) {
            this.trigger("accepted", data), this._hideOtherModals();
            var $modal = $("#meet-now-redirect-modal"),
                redirect = function () {
                    $modal.modal("hide"), window.location.href = data.lessonURL
                };
            $modal.find("button").click(redirect), $modal.modal("show"), setTimeout(redirect, 5e3)
        },
        _hideOtherModals: function () {
            this.$whatHappensModal.modal("hide"), $("#chat-proposal").modal("hide")
        },
        expired: function (data) {
            this.trigger("expired", data), this._hideOtherModals()
        },
        created: function (userID, userName, proposalID) {
            this.updateConfig(180, userID, proposalID), this.showSuccessNotification(userID)
        },
        canceled: function () {
            this.updateConfig(0)
        },
        showSuccessNotification: function (userID) {
            views.showSuccessNotification(userID, $("#meet-now-success-message"), this.$whatHappensModal).done(function (user) {
                Backbone.trigger("chat:open", user)
            })
        },
        submit: function (userID, userName, subjectID, options) {
            options = options || {};
            var self = this,
                createProposal = function (onCreate) {
                    self.meetNowProposal.createProposal(userID, userName, subjectID, options.context, onCreate, options.onError)
                },
                converted = users.Cache.currentUser.isTutor() || config.isConverted;
            if (!config.isAuthenticated || !converted) return createProposal(options.onCreate), void 0;
            options.$progress || (this.$sendingModal.find(".user-name").text(userName), this.$sendingModal.modal("show"), options.$progress = this.$sendingModal.find(".meet-now-progress"), options.onCreate = options.onCancel = options.onError = function () {
                self.$sendingModal.modal("hide")
            });
            var sendInterval, $bar = options.$progress.find(".bar"),
                $cancelButton = options.$progress.find(".js-meet-now-stop"),
                $sendingNote = options.$progress.find(".sending-note"),
                onCreate = function () {
                    $sendingNote.removeClass("delivering").addClass("delivered"), options.onCreate.apply(options.onCreate, arguments)
                },
                sendProposal = function () {
                    $cancelButton.off("click", cancelProposal).hide(), $sendingNote.removeClass("sending").addClass("delivering"), createProposal(onCreate)
                },
                cancelProposal = function () {
                    $cancelButton.off("click", cancelProposal), sendInterval && (clearInterval(sendInterval), _.isFunction(options.onCancel) && options.onCancel())
                };
            $bar.css("width", 0), $cancelButton.on("click", cancelProposal).show(), $sendingNote.removeClass("delivering delivered").addClass("sending"), options.$progress.show();
            var intervalCount = 100,
                intervalTime = 2e3 / intervalCount,
                currentInterval = 0;
            sendInterval = setInterval(function () {
                ++currentInterval, $bar.css("width", Math.ceil(100 * (currentInterval / intervalCount)) + "%"), currentInterval == intervalCount && (clearInterval(sendInterval), sendProposal())
            }, intervalTime)
        },
        showProposal: function (userID) {
            this.proposalModal.setModel().showAddLesson(userID)
        },
        setupPage: function ($container) {
            this.bindCancel($container), this.resetAll()
        },
        setupSubjects: function ($select, tutorID, studentID) {
            this.proposalModal.fetchSubjects($select, !0, studentID, tutorID)
        },
        start: function (userID, userName, context, subjectID) {
            subjectID ? this.submit(userID, userName, subjectID, {
                context: context
            }) : this.subjectModal.show(userID, userName, context)
        }
    }), new MeetNow
}), define("schedule/views", ["base/views", "base/constants", "base/notifications", "chat/models/users", "chat/view-utils", "schedule/models", "reviews/views", "config", "util"], function (views, const_, notifications, users, chatUtils, models, reviews, config, util) {
    var activeProposals, upcomingLessons, pastLessons, redirectIfParentWithoutStudent = function (uniqueUrl) {
            return config.role != const_.ROLE.PARENT || config.hasChildren ? !1 : (window.location.assign(_.sprintf("/add-student/?notify=True&tutor=%s&next=%s", uniqueUrl, window.location.pathname)), !0)
        },
        Proposals = new models.ProposalCollection,
        Lessons = new models.LessonCollection,
        SchedulingView = Backbone.Marionette.View.extend({
            $modal: null,
            initialize: function () {
                this.bindUIElements(), SchedulingView.$modal || (SchedulingView.$modal = new ProposalModalView({
                    el: $("#proposal")
                })), this.$modal = SchedulingView.$modal, this.model && this.model.bind("destroy", this.remove, this)
            },
            populateTooltip: function (e) {
                e.preventDefault(), $(e.target).tooltip("show")
            }
        }),
        ActiveProposal = SchedulingView.extend({
            events: {
                "click .open-proposal": "showRespondModal",
                "click .open-cancel-proposal": "showCancelModal",
                "click .mark-as-read": "markAsRead"
            },
            showRespondModal: function () {
                return this.$modal.setModel(this.model).showProposal(this.model.viewRespond.bind(this.model)), !1
            },
            showCancelModal: function () {
                return this.$modal.setModel(this.model).showProposal(this.model.viewCancel.bind(this.model)), !1
            },
            markAsRead: function () {
                return this.model.markAsRead(), !1
            },
            remove: function () {
                var $row = this.$el,
                    $els = [$row];
                $row.next().hasClass("original-lesson-note") && $els.push($row.next());
                var $table = $row.closest("table");
                $els.length == $table.find("tr").length ? $table.parent().parent().fadeOut("fast", function () {
                    $table.empty(), $row.remove()
                }) : $.each($els, function () {
                    $(this).fadeOut("fast", function () {
                        $(this).remove()
                    })
                })
            }
        }),
        UpcomingLesson = SchedulingView.extend({
            events: {
                "click .open-reschedule-form": "rescheduleLesson",
                "mouseover .tutor-user-cell span": "populateTooltip"
            },
            rescheduleLesson: function (event) {
                return this.$modal.setModel(this.model).showReschedule(event)
            },
            remove: function () {
                var $content = this.$el.closest(".content"),
                    $rows = $content.find(".lesson");
                this.$el.remove(), 1 === $rows.length && $content.html('<p class="blank-partial">No upcoming lessons</p>')
            }
        }),
        ActiveProposalTable = Backbone.Marionette.View.extend({
            events: {
                "mouseover .tutor-user-cell span": "populateTooltip"
            },
            initialize: function () {
                this.bindUIElements(), Proposals.on("reset", this.checkEmpty, this), Proposals.on("add", this.checkEmpty, this)
            },
            populateTooltip: function (e) {
                e.preventDefault(), $(e.target).tooltip()
            },
            checkEmpty: function () {
                0 === this.$el.find("tr").length ? this.$el.fadeOut("fast") : this.$el.show()
            },
            update: function (html) {
                Proposals.reset(), this.$el.html(html), this.generateViews(), this.checkEmpty()
            },
            generateViews: function () {
                this.$("tr.lesson").each(function () {
                    var model = new models.Proposal({
                        id: $(this).attr("data-id")
                    });
                    Proposals.add(model), new ActiveProposal({
                        model: model,
                        el: $(this)
                    })
                }), new LessonsContainer({
                    el: $("#active-proposals"),
                    dataType: "active_proposals"
                })
            }
        }),
        UpcomingLessonTable = SchedulingView.extend({
            events: {
                "click #open-proposal-form": "addNewLesson"
            },
            addNewLesson: function (event) {
                var $target = $(event.target),
                    uniqueUrl = $target.data("name");
                redirectIfParentWithoutStudent(uniqueUrl) || this.$modal.setModel(new models.Proposal(uniqueUrl)).showAddLesson()
            },
            update: function (html) {
                Lessons.reset(), this.$el.html(html), this.generateViews()
            },
            generateViews: function () {
                this.$("tr.lesson").each(function () {
                    var model = new models.Lesson({
                        id: $(this).attr("data-id"),
                        proposalID: $(this).attr("data-pid"),
                        seriesID: $(this).attr("data-series-id") || null
                    });
                    Lessons.add(model), new UpcomingLesson({
                        model: model,
                        el: $(this)
                    })
                }), new LessonsContainer({
                    el: $("#upcoming-lessons"),
                    dataType: "upcoming_lessons"
                })
            }
        }),
        ProposeNewLesson = SchedulingView.extend({
            events: {
                "click #open-proposal-form": "addNewLesson"
            },
            addNewLesson: function (event) {
                var $target = $(event.target);
                this.$modal.setModel(new models.Proposal).showAddLesson($target.attr("data-name"))
            }
        }),
        RecurringFieldView = Backbone.Marionette.View.extend({
            days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
            events: {
                "change @ui.recurringType": "recurringChanged"
            },
            ui: {
                dayDaily: ".day-daily",
                dayWeekly: ".day-weekly",
                select: "select",
                recurringType: '[name="recurring_type"]',
                recurringTypeText: ".type-text",
                recurringDetails: ".recurring-details"
            },
            initialize: function () {
                this.bindUIElements(), this.recurringType = const_.RECURRING_TYPE, this.recurringTypeValues = _.map(_.values(this.recurringType), function (n) {
                    return String(n)
                }), this.toggleEnabled()
            },
            recurringChanged: function () {
                this.toggleEnabled(this.ui.recurringType.val() || this.ui.recurringType.filter(":checked").val())
            },
            toggleEnabled: function (val) {
                _.contains(this.recurringTypeValues, val) ? (this.ui.recurringDetails.show(), Number(val) === this.recurringType.DAILY ? (this.ui.recurringTypeText.html("days"), this.ui.dayDaily.show(), this.ui.dayWeekly.hide()) : (this.ui.recurringTypeText.html("weeks"), this.ui.dayWeekly.show(), this.ui.dayDaily.hide())) : this.ui.recurringDetails.hide()
            },
            convertDay: function (dayNum) {
                return dayNum >= 0 && dayNum < this.days.length ? this.days[dayNum] : ""
            },
            setDay: function (dayNum) {
                var day = this.convertDay(dayNum);
                day && this.ui.dayWeekly.html(day)
            }
        }),
        ProposalModalView = Backbone.View.extend({
            dateInfo: {},
            savedForms: {},
            events: {
                "click #proposal-cancel": "cancelProposal",
                "click #open-counter-proposal-form": "showCounter",
                "click #open-reschedule-form": "showReschedule",
                "click #cancel-proposal-form": "showOriginalForm",
                "click #submit-counter-proposal": "submitCounter",
                "click #submit-reschedule-proposal": "submitReschedule",
                "click #show-cancel-lesson": "showCancelLesson",
                "click #cancel-single-lesson": "showCancelSingleLesson",
                "click #cancel-lesson": "cancelLesson",
                "click #cancel-lesson-series": "cancelLessonSeries",
                "click #cancel-partial-series": "cancelPartialSeries",
                "click #proposal-decline": "declineProposal",
                "click #proposal-confirm": "confirmProposal",
                "click #submit-proposal": "createProposal"
            },
            initialize: function (options) {
                options = options || {}, this.subjectCache = {}, this.prefix = options.prefix || "";
                var date = new Date(this.$(".datepicker").val());
                this.formDateHelper = new util.FormDateHelper(date.getMonth() + 1, 15), this.$el.on("hidden", function (event) {
                    event.target == this.el && this.$el.empty()
                }.bind(this)), this.timezoneHelperView = new TimezoneHelperView({
                    el: this.el,
                    formDateHelper: this.formDateHelper
                }), this.recurringField = null
            },
            updateDay: function () {
                var val = this.$(".datepicker").val();
                if (val) {
                    var d = new Date(val);
                    null !== this.recurringField && this.recurringField.setDay(d.getDay())
                }
            },
            setModel: function (model) {
                return this.model = model || new models.Proposal, this
            },
            setModelByID: function (id) {
                return this.model = new models.Proposal({
                    id: id
                }), this
            },
            _getModal: function () {
                return this.$el.modal()
            },
            showModal: function (html, size) {
                html && this.$el.html(html);
                var modal = this._getModal();
                if (!size) {
                    var n = $("#proposal-partials > li").length;
                    size = Math.min(1 == n ? 450 : 86 + 297 * n, 920)
                }
                return this.resize(size), modal
            },
            resize: function (width) {
                var margin = -Math.floor(width / 2);
                this.$el.width(width + "px").css("margin-left", margin + "px");
                var h = this.$(".modal-body").innerHeight();
                h > 400 && this.$(".modal-body").css("max-height", h + 10 + "px")
            },
            hideModal: function () {
                this.$el.modal("hide")
            },
            processFormTimeData: function () {
                var timeString = util.getDatetimeString(this.$(".datepicker"), this.$(".timepicker"));
                $("#scheduled_time").val(timeString)
            },
            setSavedForm: function (form) {
                this.savedForms[form.attr("id")] = {
                    student: form.find("#id_student").val(),
                    tutor: form.find("#id_tutor").val(),
                    date: form.find(".datepicker").val(),
                    time: form.find(".timepicker").val(),
                    timezoneTip: form.find("#timezone-tip").html(),
                    duration: form.find("#id_duration").val(),
                    note: form.find("#id_note").val()
                }
            },
            getSavedForm: function (form) {
                var savedForm = this.savedForms[form.attr("id")];
                form.find("#id_student").val(savedForm.student).trigger("liszt:updated"), form.find("#id_tutor").val(savedForm.tutor).trigger("liszt:updated"), form.find(".datepicker").val(savedForm.date), form.find(".timepicker").val(savedForm.time), form.find("#timezone-tip").html(savedForm.timezoneTip), form.find("#id_duration").val(savedForm.duration), form.find("#id_note").val(savedForm.note)
            },
            populateForm: function () {
                var time = util.getMinTime({
                    customDate: this.$("#previous-time").val()
                });
                this.$("select#id_student, select#id_tutor").chosen(), this.$(".datepicker").val(time.getMonth() + 1 + "/" + time.getDate() + "/" + time.getFullYear()).datepicker({
                    dateFormat: "m/d/yy",
                    minDate: 0,
                    maxDate: "+3M"
                }), this.$(".timepicker").timepicker({
                    forceRoundTime: !0,
                    step: 15,
                    appendTo: this.$el
                }).timepicker("setTime", time), this.recurringField = new RecurringFieldView({
                    el: this.$(".recurring-field")
                }), this.$(".datepicker").change(this.updateDay.bind(this)), this.updateDay(), this.$("#offset").val(this.formDateHelper.offset), this.userOnChangeHandler(), $("#id_student").change(this.userOnChangeHandler.bind(this)), $("#id_tutor").change(this.userOnChangeHandler.bind(this)), $(".tooltip-target").tooltip(), this.timezoneHelperView.fetchDatetimeForUser()
            },
            showAddLesson: function (user, e) {
                this.e = e, this.model.viewCreate({
                    success: this.showAddLessonSuccess.bind(this)
                }, user)
            },
            showAddLessonSuccess: function (data) {
                this.showModal(data.html, 450), this.populateForm()
            },
            showProposal: function (apiCall) {
                apiCall({
                    success: this.showProposalSuccess.bind(this),
                    error: this.showProposalError.bind(this)
                })
            },
            showProposalSuccess: function (data) {
                this.showModal(data.html), $(".tooltip-target").tooltip()
            },
            showProposalError: function (data) {
                this.showModal(data.html, 450).on("hidden", function () {
                    window.location.href = window.BASE_URL + models.ENDPOINTS.inbox
                })
            },
            showOriginalForm: function () {
                this.showProposal(this.model.viewRespond.bind(this.model))
            },
            showReschedule: function (event) {
                return this.showCounter(event, this.model.viewReschedule.bind(this.model))
            },
            showCounter: function (event, apiCall) {
                return apiCall = apiCall || this.model.viewCounter.bind(this.model), apiCall({
                    success: this.showCounterSuccess.bind(this)
                }), !1
            },
            showCounterSuccess: function (data) {
                this.showModal(data.html), this.populateForm()
            },
            submitReschedule: function (event) {
                return this.submitCounter(event, this.model.reschedule.bind(this.model))
            },
            submitCounter: function (event, apiCall) {
                this.processFormTimeData(), $("#id_note").val($("#note").val());
                var $form = $("#counter-proposal");
                return this.setSavedForm($form), $(event.target).addClass("disabled"), apiCall = apiCall || this.model.counter.bind(this.model), apiCall({
                    data: $form.serialize(),
                    success: this.submitCounterSuccess.bind(this)
                }), !1
            },
            submitCounterSuccess: function (data) {
                data.form ? (this.showModal(data.form), this.populateForm(), this.getSavedForm($("#counter-proposal"))) : data.redirect ? location.href = data.redirect : (this.hideModal(), data.isReschedule ? $("#" + this.prefix + "reschedule-success").modal() : $("#" + this.prefix + "proposal-success").modal(), activeProposals && activeProposals.update(data.activeProposals))
            },
            showCancelLesson: function () {
                null !== this.model.seriesID ? this.model.viewCancelLessonSeries({
                    success: function (data) {
                        this.$el.html(data.html)
                    }.bind(this)
                }) : this.showCancelSingleLesson()
            },
            showCancelSingleLesson: function () {
                this.model.viewCancelLesson({
                    success: function (data) {
                        this.$el.html(data.html)
                    }.bind(this)
                })
            },
            cancelLesson: function (event) {
                event.preventDefault(), this.model.cancelLesson({
                    success: function () {
                        this.model.destroy();
                        var $banner = $("#upcoming-lesson-banner");
                        notifications.addHeaderHeight(-$banner.outerHeight()), $banner.hide(), this.hideModal()
                    }.bind(this),
                    error: function (data) {
                        $("#proposal-error").html(data.error || "An error occured, please try again.").show()
                    },
                    csrf: !0
                })
            },
            cancelLessonSeries: function (evt) {
                var $btn = $(evt.target),
                    cancelAll = $btn.data("cancel-all") || !1;
                return this.model.cancelLessonSeries({
                    csrf: !0,
                    data: {
                        cancelAll: cancelAll
                    }
                }).done(function (data) {
                    data.html ? this.$el.html(data.html) : (this.hideModal(), Lessons.destroyLessons(data.canceledLessons))
                }.bind(this)).fail(function (data) {
                    $("#proposal-error").html(data.error || "An error occurred, please try again.").show()
                }), !1
            },
            cancelPartialSeries: function () {
                this.model.cancelPartialSeries({
                    csrf: !0
                }).done(function (data) {
                    data.html ? this.$el.html(data.html) : (this.hideModal(), Lessons.destroyLessons(data.canceledLessons))
                }.bind(this))
            },
            cancelProposal: function (event) {
                event.preventDefault(), this.model.cancel({
                    success: function () {
                        this.model.destroy(), this.hideModal()
                    }.bind(this),
                    error: function (data) {
                        $("#proposal-error").html(data.error || "An error occured, please try again.").show()
                    },
                    complete: function () {}
                })
            },
            declineProposal: function () {
                return this.model.decline({
                    success: this.declineSuccess.bind(this),
                    error: this.declineError.bind(this)
                }), !1
            },
            declineSuccess: function () {
                this.hideModal(), this.model.destroy()
            },
            declineError: function (data, jqXHR) {
                400 === jqXHR.status && (this.hideModal(), this.model.destroy())
            },
            confirmProposal: function (event, options) {
                var self = this;
                return $(event.target).addClass("disabled"), this.model.confirm(_.extend({
                    success: this.confirmSuccess.bind(this),
                    statusCode: {
                        403: function (data) {
                            users.Cache.getUserInfo(data.otherUser).done(function (user) {
                                self.$el.modal("hide"), "canceled" == data.reason ? $("#meet-now-canceled").find(".user-name").text(user.getFirstName()).end().modal("show") : $("#meet-now-expired").modal("show")
                            })
                        }
                    }
                }, options || {})), !1
            },
            confirmSuccess: function (data) {
                if (data.redirect) location.href = data.redirect;
                else {
                    var isReschedule = this.$(".modal-reschedule").length > 0;
                    if (activeProposals && activeProposals.update(data.activeProposals), upcomingLessons && upcomingLessons.update(data.upcomingLessons), data.upcomingLesson) {
                        var $banner = $("#upcoming-lesson-banner");
                        $banner.exists() ? $banner.replaceWith(data.upcomingLesson) : $("#main").prepend(data.upcomingLesson), views.setupUpcomingLesson()
                    }
                    this.hideModal(), isReschedule && $("#reschedule-confirmed").modal()
                }
            },
            createProposal: function () {
                var $form = $("#new-proposal"),
                    $student = $form.find("[name=student]"),
                    $tutor = $form.find("[name=tutor]"),
                    $button = $("#submit-proposal");
                return this.processFormTimeData(), $button.toggleClass("disabled").prop("disabled", !0), this.setSavedForm($form), this.model.create({
                    data: $form.serialize(),
                    success: this.createSuccess.bind(this),
                    error: function (data) {
                        if ($form.find(".errorlist").remove(), data.error) {
                            var $errorUL = $('<ul class="errorlist"><li>This field is required.</li></ul>');
                            switch (data.error) {
                            case "student":
                                $student.after($errorUL);
                                break;
                            case "tutor":
                                $tutor.after($errorUL)
                            }
                            $button.toggleClass("disabled").prop("disabled", !1)
                        }
                    }
                }), !1
            },
            createSuccess: function (data) {
                $(".tooltip-target").tooltip(), data.newForm ? (this.showModal(data.newForm, 450), this.populateForm(), this.getSavedForm($("#new-proposal"))) : data.redirect ? location.href = data.redirect : (this.hideModal(), activeProposals && activeProposals.update && activeProposals.update(data.activeProposals), showSuccessNotification(data.userID))
            },
            userOnChangeHandler: function () {
                var $idSubject = $("#id_subject"),
                    studentID = $("#id_student").val(),
                    tutorID = $("#id_tutor").val();
                studentID && tutorID && this.fetchSubjects($idSubject, !1, studentID, tutorID)
            },
            setupSelect: function (subjects, $select, meetNow) {
                var selected = $select.parent().attr("data-selected"),
                    defaultOption = meetNow ? "Select subject" : "---------";
                $select.find("option").remove();
                var option = new Option(defaultOption, "");
                $select[0].add(option);
                for (var i = 0; i < subjects.length; i++) {
                    var s = subjects[i];
                    option = new Option(s.name, s.id), s.id == selected && (option.selected = !0), $select[0].add(option)
                }
                $select.hasClass("chzn-done") ? $select.trigger("liszt:updated") : $select.chosen()
            },
            fetchSubjects: function ($target, obfuscated, studentID, tutorID) {
                var url = obfuscated ? "/schedule/get-proposal-subject-keywords-by-unique-name/" : "/schedule/get-proposal-subject-keywords/",
                    key = tutorID + ":" + studentID;
                if (key in this.subjectCache) return this.setupSelect(this.subjectCache[key], $target), void 0;
                var self = this,
                    ts = (new Date).getTime().toString();
                $.ajax({
                    url: url + "?_=" + ts,
                    type: "POST",
                    dataType: "json",
                    data: {
                        csrfmiddlewaretoken: window.CSRF_TOKEN,
                        studentID: studentID,
                        tutorID: tutorID
                    },
                    success: function (data) {
                        return data.subjects ? (self.subjectCache[key] = data.subjects, self.setupSelect(data.subjects, $target), void 0) : (window.showErrorCatchall(), void 0)
                    },
                    error: function () {
                        window.showErrorCatchall()
                    }
                })
            }
        }),
        TimezoneHelperView = Backbone.View.extend({
            timezoneTipTemplate: "In <%- name %>'s timezone, this is <%= time %><%= period %> on <%= date %>",
            sameTimezoneTipTemplate: "<%- name %> is also in this timezone",
            urls: {
                localizeDatetimeForUser: "/timezone/localize-for-user/",
                timezoneAbbr: "/timezone/abbr/"
            },
            events: {
                "change #id_student": "fetchDatetimeForUser",
                "change #id_tutor": "fetchDatetimeForUser",
                "change .datepicker": "datetimeChange",
                "change .timepicker": "datetimeChange"
            },
            initialize: function (opts) {
                this.formDateHelper = opts.formDateHelper, this.fetchDatetimeForUser()
            },
            datetimeChange: function () {
                this.fetchDatetimeForUser(), this.fetchTimezoneAbbr()
            },
            getOtherPartySelect: function () {
                return config.role === const_.ROLE.TUTOR ? this.$("select#id_student") : this.$("select#id_tutor")
            },
            getOtherPartyInput: function () {
                return config.role === const_.ROLE.TUTOR ? this.$("#id_student") : this.$("#id_tutor")
            },
            getOtherPartyID: function () {
                var $select = this.getOtherPartySelect();
                return $select.exists() ? $select.val() : this.getOtherPartyInput().val()
            },
            getOtherPartyName: function () {
                var userID, $select = this.getOtherPartySelect();
                return $select.exists() ? (userID = $select.val(), $select.children("[value=" + userID + "]").attr("data-name")) : this.getOtherPartyInput().attr("data-name")
            },
            getOtherPartyOffset: function () {
                var userID, $select = this.getOtherPartySelect();
                return $select.exists() ? (userID = $select.val(), $select.children("[value=" + userID + "]").attr("data-offset")) : this.getOtherPartyInput().attr("data-offset")
            },
            fetchDatetimeForUser: function () {
                var userID = this.getOtherPartyID(),
                    datetime = util.getDatetimeString(this.$(".datepicker"), this.$(".timepicker")),
                    offset = this.getOtherPartyOffset(),
                    name = this.getOtherPartyName();
                userID && datetime && -1 == datetime.indexOf("NaN") && (offset && Number(offset) === config.timezoneOffsetMinutes ? this.updateTimezoneTip({
                    template: this.sameTimezoneTipTemplate,
                    name: name
                }) : $.ajax({
                    url: this.urls.localizeDatetimeForUser,
                    data: {
                        userID: userID,
                        datetime: datetime
                    }
                }).done(function (data) {
                    this.updateTimezoneTip({
                        template: this.timezoneTipTemplate,
                        name: name,
                        date: data.datetime
                    })
                }.bind(this)))
            },
            fetchTimezoneAbbr: function () {
                var datetime = util.getDatetimeString(this.$(".datepicker"), this.$(".timepicker"));
                datetime && -1 == datetime.indexOf("NaN") && $.ajax({
                    url: this.urls.timezoneAbbr,
                    data: {
                        datetime: datetime,
                        timezone: config.timezone
                    }
                }).done(function (data) {
                    this.$(".timezone-abbr").html(data.timezoneAbbr)
                }.bind(this))
            },
            formatTemplateTime: function (opts) {
                var hour = opts.hour,
                    minute = opts.minute,
                    period = "am";
                return hour >= 12 && (period = "pm"), hour > 12 && (hour -= 12), hour = 0 === hour ? 12 : hour, 10 > minute && (minute = "0" + minute.toString()), {
                    hour: hour,
                    minute: minute,
                    period: period
                }
            },
            updateTimezoneTip: function (opts) {
                var text, time;
                if (opts.template === this.timezoneTipTemplate) {
                    if (!opts.date) return this.$("#timezone-tip").html(""), void 0;
                    time = this.formatTemplateTime({
                        hour: opts.date.hour,
                        minute: opts.date.minute
                    }), text = _.template(opts.template)({
                        name: opts.name,
                        time: time.hour + ":" + time.minute,
                        period: time.period,
                        date: opts.date.month + "/" + opts.date.day
                    })
                } else text = _.template(opts.template)({
                    name: opts.name
                });
                this.$("#timezone-tip").html(text)
            }
        }),
        AddNoteModal = Backbone.View.extend({
            scheduleView: null,
            $note: null,
            events: {
                "click .btn-primary": "addNote",
                "click .no-thanks": "ignoreNote"
            },
            initialize: function () {
                this.$note = this.$("textarea")
            },
            show: function (scheduleView) {
                this.scheduleView = scheduleView, this.$el.modal("show")
            },
            addNote: function (event) {
                this.$el.modal("hide"), this.scheduleView.submitForm(event, this.$note.val())
            },
            ignoreNote: function (event) {
                this.$el.modal("hide"), this.scheduleView.submitForm(event, "")
            }
        }),
        SidebarTimezoneHelperView = TimezoneHelperView.extend({
            timezoneTipTemplate: "In <%- name %>'s timezone, this is <%= time %><%= period %>"
        }),
        SchedulingSidebar = Backbone.View.extend({
            events: {
                "click .profile-page": "submitForm",
                "click .question-page": "showAddNote",
                "change .datepicker": "updateDay"
            },
            initialize: function (options) {
                var time = util.getMinTime();
                SchedulingSidebar.AddNoteModal || (SchedulingSidebar.AddNoteModal = new AddNoteModal({
                    el: $("#add-note")
                })), this.dateHelper = new util.FormDateHelper((new Date).getMonth() + 1, 15), options.deferChosen || this.$('[name="subject"]').chosen();
                var $timepicker = this.$(".timepicker");
                $timepicker.exists() && (this.$(".datepicker").val(time.getMonth() + 1 + "/" + time.getDate() + "/" + time.getFullYear()).datepicker({
                    dateFormat: "m/d/yy",
                    minDate: 0,
                    maxDate: "+3M"
                }), $timepicker.timepicker({
                    forceRoundTime: !0,
                    step: 15
                }).timepicker("setTime", time)), this.timezoneHelperView = new SidebarTimezoneHelperView({
                    el: this.el,
                    formDateHelper: this.dateHelper
                }), this.recurringField = new RecurringFieldView({
                    el: this.$(".recurring-field")
                }), this.updateDay()
            },
            updateDay: function () {
                var val = this.$(".datepicker").val();
                if (val) {
                    var d = new Date(val);
                    null !== this.recurringField && this.recurringField.setDay(d.getDay())
                }
            },
            showAddNote: function () {
                return SchedulingSidebar.AddNoteModal.show(this), !1
            },
            submitForm: function (event, noteValue) {
                noteValue = noteValue || $("#id_body").val(), this.$('[name="body"]').val(noteValue);
                var timeString = util.getDatetimeString(this.$(".datepicker"), this.$(".timepicker"));
                this.$('[name="scheduled_time"]').val(timeString);
                var $button = this.$(".btn-primary");
                $button.button("loading");
                var proposal = new models.Proposal;
                return proposal.validate_({
                    data: this.$el.serialize(),
                    success: function (data) {
                        if (data.redirectURL) return window.location.href = data.redirectURL, void 0;
                        if ($button.button("reset"), this.$("ul.errorlist").addClass("hidden-content"), data.errors)
                            for (var e = 0; e < data.errors.length; e++) {
                                var error = data.errors[e];
                                this.$("." + error[0] + "_errors").html(error[1]), this.$("." + error[0] + "_errors").parent().removeClass("hidden-content")
                            }
                    }.bind(this)
                }), !1
            }
        }),
        LessonsContainer = Backbone.Marionette.View.extend({
            events: {
                "click .pagination-container a": "fetchPage",
                "mouseover .review-cell": "populateTooltip",
                "mouseover .tutor-review-cell": "populateTooltip",
                "mouseover .tutor-user-cell span": "populateTooltip",
                "click .review-cell a": "showReviewModal"
            },
            initialize: function (options) {
                this.bindUIElements(), this.options = options
            },
            populateTooltip: function (e) {
                e.preventDefault(), $(e.target).tooltip("show")
            },
            fetchPage: function (e) {
                var $a = $(e.target),
                    $container = this.$(".content").parent(),
                    dataType = this.options.dataType,
                    url = $a.attr("href"),
                    data = {
                        dataType: dataType
                    };
                e.preventDefault(), $.ajax(url, {
                    data: data,
                    success: function (data) {
                        $container.html(data.html)
                    }
                })
            },
            showReviewModal: function (event) {
                var $target = $(event.target),
                    lessonCode = $target.data("lesson-code"),
                    tutorName = $target.data("tutor-name");
                event.preventDefault(), this.$modal.show(lessonCode, tutorName, $target.parent())
            }
        }),
        showSuccessNotification = function (userID, $messageEl, $whatHappensModal) {
            return $messageEl = $messageEl || $("#proposal-success-message"), $whatHappensModal = $whatHappensModal || $("#proposal-what-happens-modal"), users.Cache.getUserInfo(userID).done(function (user) {
                var name = _(user.getName()).rtrim("."),
                    period = _(user.getName()).endsWith(".") ? "." : "",
                    message = $messageEl.find(".user-name").text(name).end().find(".period").text(period).end().html();
                notifications.show({
                    message: message,
                    showIcon: !0,
                    timeVisible: 8e3,
                    extend: {
                        events: {
                            "click a": "showWhatHappens"
                        },
                        showWhatHappens: function () {
                            this.hide();
                            var pronouns = chatUtils.getGenderPronouns(user.getGender());
                            $whatHappensModal.find(".user-name").text(name).end().find(".period").text(period).end().find(".gender-pronoun").text(pronouns.subjective).end().find(".gender-plural").text(pronouns.plural).end().modal("show")
                        }
                    }
                })
            })
        };
    return {
        setupActiveProposals: function () {
            activeProposals = new ActiveProposalTable({
                el: $("#active-proposals")
            }), activeProposals.generateViews()
        },
        setupUpcomingLessons: function () {
            upcomingLessons = new UpcomingLessonTable({
                el: $("#upcoming-lessons")
            }), upcomingLessons.generateViews()
        },
        setupSchedulingSidebar: function () {
            $(".schedule-with-tutor-form").each(function () {
                new SchedulingSidebar({
                    el: $(this)
                })
            })
        },
        setupPastLessons: function () {
            return pastLessons = new LessonsContainer({
                el: $("#past-lessons"),
                dataType: "past_lessons"
            }), pastLessons.$modal = new reviews.LessonReviewModal({
                el: $("#submit-review-modal")
            }), pastLessons
        },
        setupLessonsPage: function () {
            this.setupActiveProposals(), this.setupUpcomingLessons(), this.setupPastLessons(), new ProposeNewLesson({
                el: $("#scheduling-container")
            })
        },
        setupIndexPage: function () {
            this.setupActiveProposals(), this.setupUpcomingLessons(), this.setupPastLessons()
        },
        RecurringFieldView: RecurringFieldView,
        SchedulingSidebar: SchedulingSidebar,
        UpcomingLessonTable: UpcomingLessonTable,
        ProposalModalView: ProposalModalView,
        ProposeNewLesson: ProposeNewLesson,
        redirectIfParentWithoutStudent: redirectIfParentWithoutStudent,
        showSuccessNotification: showSuccessNotification
    }
}), define("tutor-training/page-tutor-training", ["tutor-training/views", "tutor-training/models"], function (v, m) {
    var createSubStep = function (selector, position, name) {
            return new v.SubStepView({
                el: $(selector),
                model: new m.SubStep({
                    position: position,
                    name: name
                })
            })
        },
        beginTraining = new v.BeginView({
            el: $("#begin-training"),
            model: new m.BeginStep({
                position: 1,
                ignore: !0
            })
        }),
        ourLessonSpaceProceed = new v.VideoProceedView({
            el: $("#our-lesson-space .next-step-section"),
            model: new m.Step({
                position: 7,
                ignore: !0,
                name: "our-lesson-space:proceed"
            })
        }),
        ourLessonSpaceSteps = v.ourLessonSpaceGenerator(m.VideoStep, [ourLessonSpaceProceed.model]);
    ourLessonSpaceProceed.listenTo(ourLessonSpaceSteps, "change:finished", ourLessonSpaceProceed.deferredStart);
    var $odl = $("#on-demand-lessons"),
        onDemandLessonsSteps = new m.Steps([createSubStep($odl.find(".what-are-they"), 1, "on-demand-lessons:what-are-they").model, createSubStep($odl.find(".how-to-get"), 2, "on-demand-lessons:how-to-get").model, createSubStep($odl.find(".when-to-accept"), 3, "on-demand-lessons:when-to-accept").model, new v.ProceedView({
            el: $odl.find(".next-step-section"),
            model: new m.Step({
                position: 4,
                ignore: !0,
                name: "on-demand-lessons:proceed"
            })
        }).model], {
            step: new v.StepView({
                el: $odl,
                model: new m.Step({
                    position: 3,
                    name: "on-demand-lessons"
                })
            }).model
        }),
        $sl = $("#scheduled-lessons"),
        scheduledLessonsSteps = new m.Steps([createSubStep($sl.find(".what-are-they"), 1, "scheduled-lessons:what-are-they").model, createSubStep($sl.find(".how-to-get"), 2, "scheduled-lessons:how-to-get").model, createSubStep($sl.find(".what-if-reschedule"), 3, "scheduled-lessons:what-if-reschedule").model, new v.ProceedView({
            el: $sl.find(".next-step-section"),
            model: new m.Step({
                position: 4,
                ignore: !0,
                name: "scheduled-lessons:proceed"
            })
        }).model], {
            step: new v.StepView({
                el: $sl,
                model: new m.Step({
                    position: 4,
                    name: "scheduled-lessons"
                })
            }).model
        }),
        $wl = $("#written-lessons"),
        writtenLessonsSteps = new m.Steps([createSubStep($wl.find(".what-are-they"), 1, "written-lessons:what-are-they").model, createSubStep($wl.find(".how-to-get"), 2, "written-lessons:how-to-get").model, createSubStep($wl.find(".how-does-time-work"), 3, "written-lessons:how-does-time-work").model, new v.ProceedView({
            el: $wl.find(".next-step-section"),
            model: new m.Step({
                position: 4,
                ignore: !0,
                name: "written-lessons:proceed"
            })
        }).model], {
            step: new v.StepView({
                el: $wl,
                model: new m.Step({
                    position: 5,
                    name: "written-lessons"
                })
            }).model
        }),
        $an = $("#training-available-now"),
        availableNowLessonsSteps = new m.Steps([createSubStep($an.find(".what-does-it-mean"), 1, "available-now:what-does-it-mean").model, createSubStep($an.find(".how-do-i-set"), 2, "available-now:how-do-i-set").model, createSubStep($an.find(".turned-off"), 3, "available-now:turned-off").model, new v.ProceedView({
            el: $an.find(".next-step-section"),
            model: new m.Step({
                position: 4,
                ignore: !0,
                name: "available-now:proceed"
            })
        }).model], {
            step: new v.StepView({
                el: $an,
                model: new m.Step({
                    position: 6,
                    name: "written-lessons"
                })
            }).model
        }),
        $faq = $("#student-faqs"),
        studentFAQsSteps = new m.Steps([createSubStep($faq.find(".do-i-have-to-pay"), 1, "student-faqs:do-i-have-to-pay").model, createSubStep($faq.find(".how-much-cost"), 2, "student-faqs:how-much-cost").model, createSubStep($faq.find(".will-you-do"), 3, "student-faqs:will-you-do").model, new v.ProceedView({
            el: $faq.find(".next-step-section"),
            model: new m.Step({
                position: 4,
                ignore: !0,
                name: "student-faqs:proceed"
            })
        }).model], {
            step: new v.StepView({
                el: $faq,
                model: new m.Step({
                    position: 7,
                    name: "student-faqs"
                })
            }).model
        }),
        steps = new m.Steps([beginTraining.model, ourLessonSpaceSteps.step, onDemandLessonsSteps.step, scheduledLessonsSteps.step, writtenLessonsSteps.step, availableNowLessonsSteps.step, studentFAQsSteps.step], {
            step: new m.Step
        });
    beginTraining.listenTo(steps, "change:finished", beginTraining.updatePercentageOnFinish);
    var TutorTrainingRouter = Backbone.Router.extend({
        routes: {
            "": "loadBackEndStep",
            ":stepName/:subStepName": "loadStep"
        },
        initialize: function (options) {
            this.stepURL = options.stepURL
        },
        loadBackEndStep: function () {
            if ("NOT_STARTED" != this.stepURL && "LEGACY" != this.stepURL) {
                var splitURL = _.words(this.stepURL, /:/);
                this.loadStep(splitURL[0], splitURL[1])
            }
        },
        loadStep: function (stepName, subStepName) {
            var step = steps.findWhere({
                    name: stepName
                }),
                subStep = step.steps.findWhere({
                    name: stepName + ":" + subStepName
                });
            m.latestStepHandler.setPosition(step.get("position"), subStep.get("position"));
            for (var i = 0; i < step.get("position") - 1; i++) {
                var previousStep = steps.at(i);
                if (previousStep.display(), previousStep.steps) {
                    previousStep.steps.at(0).display();
                    for (var j = 0; j < previousStep.steps.length; j++) previousStep.steps.at(j).finish()
                }
            }
            for (i = 0; i < subStep.get("position") - 1; i++) step.steps.at(i).finish();
            step.start(subStep.get("position")), beginTraining.updatePercentage(step.get("position") - 1)
        }
    });
    return {
        TutorTrainingRouter: TutorTrainingRouter
    }
}), define("tutor-training/page-tutor-guide", ["tutor-training/views", "tutor-training/models", "util"], function (v, m, util) {
    var ourLessonSpaceSteps = v.ourLessonSpaceGenerator(m.TutorGuideVideoStep),
        TutorGuideRouter = Backbone.Router.extend({
            routes: {
                ":step/:subStep": "scrollToSection",
                "video/:step/:subStep": "playVideo"
            },
            scrollToSection: function (step, subStep) {
                util.scrollToElement(_.sprintf("#%s .%s", step, subStep), 60)
            },
            playVideo: function (step, subStep) {
                util.scrollToElement("#" + step, 10);
                var video = ourLessonSpaceSteps.findWhere({
                    name: _.sprintf("%s:%s", step, subStep)
                });
                video && video.display()
            }
        });
    return {
        ourLessonSpaceSteps: ourLessonSpaceSteps,
        TutorGuideRouter: TutorGuideRouter
    }
}), define("tutor-training/models", ["util"], function (util) {
    var latestStepHandler = function () {
            var _stepPosition = 0,
                _subStepPosition = 0,
                setPosition = function (stepPosition, subStepPosition) {
                    _stepPosition = stepPosition, _subStepPosition = subStepPosition
                };
            return {
                setPosition: setPosition,
                updatePosition: function (subStep) {
                    if (!subStep.get("ignore")) {
                        var subStepPosition = subStep.get("position"),
                            parentPosition = subStep.getParentStep().get("position");
                        _stepPosition > parentPosition || parentPosition == _stepPosition && _subStepPosition >= subStepPosition || (util.API.post("/orientation/", {
                            csrf: !0,
                            checkDataForDoubleSubmit: !0,
                            data: {
                                step: subStep.get("name")
                            }
                        }), setPosition(parentPosition, subStepPosition))
                    }
                }
            }
        }(),
        Step = Backbone.Model.extend({
            defaults: {
                finished: !1,
                ignore: !1
            },
            display: function () {
                this.trigger("display")
            },
            start: function (subStep) {
                this.trigger("start", subStep)
            },
            markComplete: function () {
                this.trigger("markComplete")
            },
            forward: function () {
                this.finish(), this.trigger("forward", this)
            },
            back: function () {
                this.finish(), this.trigger("back", this)
            },
            finish: function () {
                this.set("finished", !0)
            },
            isFirst: function () {
                return 1 == this.get("position")
            },
            isFinished: function () {
                return this.get("finished")
            },
            getParentStep: function () {
                return this.collection ? this.collection.step : void 0
            }
        }),
        Steps = Backbone.Collection.extend({
            model: Step,
            comparator: function (model) {
                return model.get("position")
            },
            extraInit: function () {},
            initialize: function (models, options) {
                this.step = options.step, this.step.steps = this, this.listenToOnce(this.step, "start", this.start), this.on({
                    forward: this.forward,
                    back: this.back
                }), this.extraInit()
            },
            start: function (subStep) {
                subStep ? subStep-- : subStep = 0, this.at(subStep).start(subStep)
            },
            forward: function (model) {
                var nextStep = this.findWhere({
                    position: model.get("position") + 1
                });
                nextStep && nextStep.start()
            },
            back: function (model) {
                var previousStep = this.findWhere({
                    position: model.get("position") - 1
                });
                previousStep && previousStep.start()
            },
            countFinishedSteps: function () {
                return this.where({
                    finished: !0
                }).length
            },
            getUsefulLength: function () {
                return this.where({
                    ignore: !1
                }).length
            }
        }),
        VideoSteps = Steps.extend({
            extraInit: function () {
                this.on("videoLoaded", function () {
                    this.step.trigger("videoLoaded")
                })
            }
        }),
        SubStep = Step.extend({
            start: function () {
                this.trigger("start"), latestStepHandler.updatePosition(this), this.isLast() && this.forward()
            },
            isLast: function () {
                return 0 === this.collection.getUsefulLength() - this.get("position")
            }
        }),
        BeginStep = Step.extend({
            updatePercentage: function (modelPosition) {
                return (modelPosition - 1) / this.collection.getUsefulLength()
            }
        }),
        VideoStep = Step.extend({
            start: function (subStep) {
                this.trigger("start", subStep), latestStepHandler.updatePosition(this)
            },
            onVideoProgress: function (videoData) {
                !this.isFinished() && videoData.duration - videoData.seconds < 5 && this.forward()
            }
        }),
        TutorGuideVideoStep = VideoStep.extend({
            start: function () {
                this.trigger("start")
            }
        });
    return {
        Step: Step,
        Steps: Steps,
        SubStep: SubStep,
        BeginStep: BeginStep,
        VideoStep: VideoStep,
        TutorGuideVideoStep: TutorGuideVideoStep,
        VideoSteps: VideoSteps,
        latestStepHandler: latestStepHandler
    }
}), define("tutor-training/views", ["tutor-training/models", "util"], function (m, util) {
    var StepView = Backbone.Marionette.View.extend({
            ui: {
                stepNumber: ".flow-step-number",
                stepStatus: ".step-status",
                proceed: ".next-step-section"
            },
            events: {
                "click .forward-step:not(.disabled)": "forward"
            },
            modelEvents: {
                start: "start",
                display: "display",
                "change:finished markComplete": "markComplete"
            },
            initialize: function () {
                this.bindUIElements()
            },
            start: function () {
                this.show(), this.ui.proceed.show(), util.scrollTop(this.$el.offset().top, 20)
            },
            display: function () {
                this.show(), this.markComplete()
            },
            show: function () {
                this.$el.css("visibility", "visible")
            },
            forward: function () {
                this.model.forward()
            },
            markComplete: function () {
                this.ui.stepStatus.html("Completed").addClass("completed")
            },
            finish: function () {
                this.$el.hide()
            }
        }),
        SubStepView = StepView.extend({
            ui: {
                backButton: ".back-substep",
                forwardButton: ".forward-substep",
                slideCompleted: ".slide-completed",
                navigation: ".slide-navigation"
            },
            events: {
                "click .forward-substep": "forward",
                "click .back-substep": "back"
            },
            display: function () {
                this.start()
            },
            initialize: function () {
                this.bindUIElements(), this.markedComplete = !1, this.template = _.template($("#slide-navigation-template").html())
            },
            start: function () {
                this.ui.navigation.html(this.template({
                    isFirst: this.model.isFirst(),
                    isLast: this.model.isLast(),
                    slideNumber: this.model.get("position"),
                    totalSlides: this.model.collection.getUsefulLength()
                })), this.$el.show(), this.model.isLast() && this.markComplete()
            },
            forward: function () {
                this.model.isLast() || this.finish(), this.model.forward()
            },
            back: function () {
                this.model.isFirst() || this.finish(), this.model.back()
            },
            markComplete: function () {
                this.markedComplete || (this.ui.slideCompleted.css({
                    visibility: "visible",
                    opacity: 0
                }).animate({
                    opacity: 1
                }, 500), this.markedComplete = !0)
            }
        }),
        ProceedView = StepView.extend({
            ui: {
                forwardButton: ".forward-step",
                disabledCopy: ".next-step-disabled-copy",
                enabledCopy: ".next-step-enabled-copy"
            },
            start: function () {
                this.ui.forwardButton.removeClass("disabled"), this.ui.disabledCopy.hide(), this.ui.enabledCopy.removeClass("hidden-content")
            },
            forward: function () {
                this.model.forward(), this.finish()
            },
            finish: function () {
                this.$el.hide()
            }
        }),
        BeginView = StepView.extend({
            ui: {
                beginButton: "#begin-training-button",
                percentCompleted: "#percent-completed"
            },
            start: function () {},
            finish: function () {},
            forward: function () {
                this.model.forward(), this.finish()
            },
            updatePercentageOnFinish: function (lastFinishedModel) {
                var completion = this.model.updatePercentage(lastFinishedModel.get("position"));
                this._updatePercentage(completion)
            },
            updatePercentage: function (modelPosition) {
                var completion = this.model.updatePercentage(modelPosition);
                this._updatePercentage(completion)
            },
            _updatePercentage: function (completion) {
                this.ui.beginButton.hide(), this.ui.percentCompleted.html(_.sprintf("You are %d%% complete", 100 * completion))
            }
        }),
        VideoProceedView = ProceedView.extend({
            start: function () {},
            deferredStart: function (model) {
                model.collection.countFinishedSteps() == model.collection.getUsefulLength() && (this.ui.forwardButton.removeClass("disabled"), this.ui.disabledCopy.hide(), this.ui.enabledCopy.removeClass("hidden-content"))
            }
        }),
        VideoStepView = StepView.extend({
            ui: {
                stepNumber: ".flow-step-number",
                stepStatus: ".step-status",
                proceed: ".next-step-section",
                videoCards: ".video-card",
                playingIndicators: ".playing-indicator"
            },
            modelEvents: {
                start: "start",
                "change:finished": "markComplete",
                videoLoaded: "clearPlaying"
            },
            clearPlaying: function () {
                this.ui.videoCards.removeClass("playing"), this.ui.playingIndicators.fadeOut("fast")
            },
            markComplete: function () {
                StepView.prototype.markComplete.call(this), this.clearPlaying()
            }
        }),
        VideoSubStepView = SubStepView.extend({
            ui: {
                playButton: ".play",
                stepCompleted: ".step-completed",
                duration: ".duration",
                playingIndicator: ".playing-indicator",
                videoFinishedIcon: ".video-finished-icon"
            },
            events: {
                "click .play": "playVideo"
            },
            initialize: function () {
                this.bindUIElements(), this.ui.video = $(this.attributes.video)
            },
            start: function (loadImmediately) {
                (this.model.isFirst() || loadImmediately) && this.loadVideo()
            },
            display: function () {
                this.loadVideo()
            },
            markComplete: function () {
                this.ui.videoFinishedIcon.fadeIn("fast")
            },
            loadVideo: function (playImmediately) {
                this.model.trigger("videoLoaded");
                var width = this.ui.video.width(),
                    height = this.ui.video.height(),
                    html = _.sprintf('<iframe class="vimeo" src="http://player.vimeo.com/video/%s?api=1" width="%d" height="%d" frameborder="0"></iframe>', this.model.get("vimeoID"), width, height);
                this.ui.video.html(html), this.videoPlayer = window.$f(this.ui.video.find("iframe")[0]), this.videoPlayer.addEvent("ready", function () {
                    this.videoPlayer.addEvent("playProgress", this.model.onVideoProgress.bind(this.model)), this.$el.addClass("playing"), this.ui.playingIndicator.fadeIn("fast"), playImmediately && this.videoPlayer.api("play")
                }.bind(this))
            },
            playVideo: function () {
                this.loadVideo(!0)
            }
        }),
        Sidebar = Backbone.Marionette.View.extend({
            events: {
                "click .header.inactive": "showSection",
                "click .header.active": "hideSection",
                "click .link": "navigate"
            },
            ui: {
                activeHeader: ".header.active",
                section: ".sidebar-section-fold"
            },
            showSection: function (e) {
                this.$(".header.active").removeClass("active").addClass("inactive").next(".sidebar-section-fold").slideUp("fast").removeClass("open");
                var $header = $(e.target);
                $header.removeClass("inactive").addClass("active").next(".sidebar-section-fold").slideDown("fast").addClass("open")
            },
            hideSection: function (e) {
                var $header = $(e.target);
                $header.addClass("inactive").removeClass("active").next(".sidebar-section-fold").slideUp("fast")
            },
            initialize: function () {
                this.$el.affix({
                    offset: util.topNavHeight - 25
                })
            },
            navigate: function (e) {
                return Backbone.history.navigate(e.target.getAttribute("href"), {
                    trigger: !0
                }), !1
            }
        }),
        ourLessonSpaceGenerator = function (StepClass, extraModels) {
            return extraModels = extraModels || [], new m.VideoSteps(extraModels.concat([new VideoSubStepView({
                el: "#our-lesson-space .communication-tools",
                attributes: {
                    video: "#our-lesson-space .video-player"
                },
                model: new StepClass({
                    position: 1,
                    vimeoID: 76003719,
                    name: "our-lesson-space:communication-tools"
                })
            }).model, new VideoSubStepView({
                el: "#our-lesson-space .whiteboard",
                attributes: {
                    video: "#our-lesson-space .video-player"
                },
                model: new StepClass({
                    position: 2,
                    vimeoID: 76003718,
                    name: "our-lesson-space:whiteboard"
                })
            }).model, new VideoSubStepView({
                el: "#our-lesson-space .text-editor",
                attributes: {
                    video: "#our-lesson-space .video-player"
                },
                model: new StepClass({
                    position: 3,
                    vimeoID: 76003716,
                    name: "our-lesson-space:text-editor"
                })
            }).model, new VideoSubStepView({
                el: "#our-lesson-space .code-editor",
                attributes: {
                    video: "#our-lesson-space .video-player"
                },
                model: new StepClass({
                    position: 4,
                    vimeoID: 76003661,
                    name: "our-lesson-space:code-editor"
                })
            }).model, new VideoSubStepView({
                el: "#our-lesson-space .screensharing",
                attributes: {
                    video: "#our-lesson-space .video-player"
                },
                model: new StepClass({
                    position: 5,
                    vimeoID: 84073338,
                    name: "our-lesson-space:screensharing"
                })
            }).model, new VideoSubStepView({
                el: "#our-lesson-space .pause-and-void",
                attributes: {
                    video: "#our-lesson-space .video-player"
                },
                model: new StepClass({
                    position: 6,
                    vimeoID: 76003717,
                    name: "our-lesson-space:pause-and-void"
                })
            }).model]), {
                step: new VideoStepView({
                    el: $("#our-lesson-space"),
                    model: new m.Step({
                        position: 2,
                        name: "our-lesson-space"
                    })
                }).model
            })
        };
    return {
        StepView: StepView,
        SubStepView: SubStepView,
        BeginView: BeginView,
        ProceedView: ProceedView,
        VideoProceedView: VideoProceedView,
        VideoStepView: VideoStepView,
        VideoSubStepView: VideoSubStepView,
        Sidebar: Sidebar,
        ourLessonSpaceGenerator: ourLessonSpaceGenerator
    }
}), define("subjects/search", ["util"], function (util) {
    var keywords = window.getKeywords(),
        lowerKeywords = _(keywords).map(function (keyword) {
            return keyword.toLowerCase()
        }),
        SubjectSearchView = Backbone.Marionette.View.extend({
            ui: {
                subject: "input[type=text]",
                button: "button",
                label: "label"
            },
            events: {
                "click #subject-search-btn": "submitSubject",
                "keydown input[type=text]": "keydown"
            },
            initialize: function () {
                this.bindUIElements(), this.submitting = !1, this.failedSearches = 0, this.ui.subject.autocomplete({
                    minLength: 2,
                    source: keywords,
                    select: function (event, ui) {
                        event.preventDefault(), this.setSubject(ui.item.value), this.submitSubject()
                    }.bind(this)
                })
            },
            setSubject: function (text) {
                this.ui.subject.val(text)
            },
            keydown: function (event) {
                if (util.isEnterKey(event)) {
                    var subject = this.ui.subject.val();
                    return _.isBlank(subject) || this.submitSubject(), !1
                }
                return !0
            },
            submitSubject: function () {
                var subject = this.ui.subject.val();
                return this.submitting ? !1 : (this.startSubmit(), $.ajax({
                    url: window.TRACK_SEARCH_URL,
                    type: "GET",
                    dataType: "json",
                    cache: !1,
                    data: {
                        q: subject
                    },
                    complete: this.subjectSubmitted.bind(this)
                }), !1)
            },
            startSubmit: function () {
                this.submitting = !0, this.ui.button.button("loading")
            },
            finishSubmit: function () {
                this.submitting = !1, this.setSubject(""), this.ui.button.button("reset")
            },
            subjectSubmitted: function () {
                var subject = this.ui.subject.val();
                if (_.isBlank(subject)) return this.redirectToBrowsePage("empty");
                if (!_(lowerKeywords).contains(subject.toLowerCase())) {
                    if (this.failedSearches += 1, this.failedSearches > 1) return this.redirectToBrowsePage("failed");
                    $("#popup-content").html($("#subject-search-failed").html()), window.showLightbox();
                    var subjectOffset = this.ui.subject.offset();
                    return $("#popup").css("top", Math.max(subjectOffset.top - 126, 53) + "px"), this.finishSubmit(), void 0
                }
                subject = this.getEscapedSubject(subject), window.location.href = "/" + subject + "-online-tutoring/"
            },
            redirectToBrowsePage: function (searchStatus) {
                var url = "/online-tutors/";
                return "empty" === searchStatus ? url += "?es" : "failed" === searchStatus && (url += "?fs"), window.location.href = url, !1
            },
            getEscapedSubject: function (subject) {
                return subject.replace(/[^A-Za-z0-9/\+\t\n\r\- ]/g, "").replace(/[/\t\n\r\- ]+/g, "-")
            }
        });
    return {
        SubjectSearchView: SubjectSearchView
    }
}), define("experts/availability", ["chat/constants", "chat/view-utils", "schedule/meet-now", "events", "config", "util", "socket"], function (chatConstants, chatUtils, meetNow, events, config, util, socket) {
    var Toggles = Backbone.Marionette.View.extend({
            CONTEXT: "sidebar",
            ui: {
                containers: ".switch-container"
            },
            events: {
                "click @ui.containers": "toggle"
            },
            TOGGLES: [],
            initialize: function () {
                this.bindUIElements(), this.TOGGLES.push(this)
            },
            getActiveCount: function () {
                return this.ui.containers.filter(".active").length
            },
            updateState: function (toggleType) {
                var $type = this.$("[data-toggle-type=" + toggleType + "]");
                $type.toggleClass("active")
            },
            toggle: function (event) {
                var $target = $(event.target).closest(".switch-container"),
                    toggleType = $target.data("toggle-type"),
                    toggleOn = !$target.hasClass("active");
                _(this.TOGGLES).each(function (toggle) {
                    toggle.updateState(toggleType)
                }), util.API.post("/expert/update-availability/", {
                    csrf: !0,
                    checkDataForDoubleSubmit: !0,
                    data: {
                        toggle: toggleType,
                        value: toggleOn
                    },
                    success: function () {
                        events.create(events.EVENT.AVAILABLE_NOW_SETTING_CHANGED, {
                            setting: toggleType,
                            state: toggleOn,
                            context: this.CONTEXT
                        })
                    }.bind(this),
                    error: function () {
                        this.updateState(toggleType)
                    }.bind(this)
                })
            }
        }),
        TogglesModal = Toggles.extend({
            STORAGE_KEY: "hide-toggles-modal",
            CONTEXT: "modal",
            ui: {
                checkbox: "input[name=disable-modal]"
            },
            events: {
                "change @ui.checkbox": "toggleVisibility"
            },
            hideTogglesModal: function (value) {
                return _.isUndefined(value) || (window.localStorage[this.STORAGE_KEY] = value ? 1 : 0), 1 == window.localStorage[this.STORAGE_KEY]
            },
            toggleVisibility: function () {
                var checked = this.ui.checkbox.is(":checked");
                this.hideTogglesModal(checked), events.create(events.EVENT.AVAILABLE_NOW_DONT_SHOW_MODAL, {
                    state: checked
                })
            },
            show: function () {
                if (!this.hideTogglesModal()) {
                    this.$el.removeClass("some-enabled none-enabled");
                    var count = this.getActiveCount();
                    0 === count ? this.$el.addClass("none-enabled").modal("show") : 3 > count && this.$el.addClass("some-enabled").modal("show")
                }
            },
            hide: function () {
                this.$el.modal("hide")
            }
        }),
        AvailableNow = Backbone.Marionette.View.extend({
            ui: {
                available: ".available",
                busy: ".busy",
                "default": ".default"
            },
            events: {
                "click @ui.available": "setAvailable",
                "click @ui.default": "setNotAvailable"
            },
            initialize: function () {
                this.bindUIElements();
                var self = this;
                this.isAvailable = this.ui.available.hasClass("selected"), this.$headerButton = $("#available-now"), this.togglesModal = new TogglesModal({
                    el: "#availability-toggles-modal"
                }), this.$idleModal = $("#availability-now-idle-modal"), this.$idleModalMeetNowExpired = $("#availability-now-meetnow-expired-modal"), this.$idleModalInteractionExpired = $("#availability-now-interaction-expired");
                var idleModals = [this.$idleModal, this.$idleModalMeetNowExpired, this.$idleModalInteractionExpired];
                _.each(idleModals, function ($modal) {
                    $modal.find(".js-still-available").on("click", function () {
                        self.setAvailable(), $modal.modal("hide"), events.create(events.EVENT.AVAILABLE_NOW_STILL_AVAILABLE, {
                            context: $modal.prop("id")
                        })
                    })
                }), this.setupSocket(), meetNow.on("received accepted", function () {
                    this.$idleModal.modal("hide")
                }.bind(this)), meetNow.on("expired", function () {
                    this.$idleModalMeetNowExpired.modal("show"), this.updateUI(!1)
                }.bind(this))
            },
            setupSocket: function () {
                var self = this;
                socket.subscribe("user=" + config.uid, {
                    "chat:update.availability": function (data) {
                        if (data.user.id == config.uuid && data.user.ieduAvailability) {
                            var _const = chatConstants.AVAILABILITY,
                                isAway = data.user.ieduAvailability == _const.AWAY;
                            self.isAvailable && isAway && !data.user.isBusy && !meetNow.hasOpenProposalModal() && (self.togglesModal.hide(), self.$idleModal.modal("show"), chatUtils.playChatSound()), self.isAvailable != data.user.availableNow && (self.isAvailable = data.user.availableNow, self.updateUI(self.isAvailable), self.isAvailable && self.$idleModal.modal("hide")), self.updateUI(self.isAvailable, data.user.isBusy)
                        }
                    },
                    "chat:update.interaction_timeout": function () {
                        self.isAvailable && (self.$idleModalInteractionExpired.modal("show"), self.updateUI(!1))
                    }
                })
            },
            checkToggles: function () {
                this.togglesModal.show()
            },
            updateUI: function (isAvailable, isBusy) {
                isAvailable ? (this.ui.available.addClass("selected"), this.ui.default.removeClass("selected")) : (this.ui.available.removeClass("selected"), this.ui.default.addClass("selected")), this.$el.removeClass("busy"), this.$headerButton.removeClass("busy default"), isBusy ? (this.$el.addClass("busy"), this.$headerButton.addClass("busy")) : isAvailable || this.$headerButton.addClass("default")
            },
            setAvailable: function () {
                return this.updateUI(!0), this._updateBackend(!0) && this.checkToggles(), this.$el.dropdown("toggle"), !1
            },
            setNotAvailable: function () {
                return this.updateUI(!1), this._updateBackend(!1), this.$el.dropdown("toggle"), !1
            },
            _updateBackend: function (isAvailable) {
                if (isAvailable == this.isAvailable) return !1;
                this.isAvailable = isAvailable;
                var self = this;
                return util.API.post("expert/available-now/", {
                    csrf: !0,
                    data: {
                        isAvailable: isAvailable
                    },
                    error: function (data) {
                        self.isAvailable = !isAvailable, self.updateUI(self.isAvailable, data.isBusy)
                    }
                }), !0
            }
        });
    return {
        Toggles: Toggles,
        AvailableNow: AvailableNow
    }
}), define("experts/messages", ["profiles/views", "util"], function (profiles, util) {
    var MessageForm = Backbone.View.extend({
            ENDPOINTS: {},
            events: {
                "click .js-send-button": "submitForm"
            },
            initialize: function (options) {
                this.$filterForm = options.$filterForm, this.$form = this.$el, this.$messageSubmit = this.$(".message-submit"), this.$toolbar = this.$("#sendmessage-toolbar"), this.updateEndpoints(options), this.$('select[name$="subject"], select[name="filter-subjects"]').chosen()
            },
            updateEndpoints: function (options) {
                this.ENDPOINTS = _.extend(options.ENDPOINTS || {}, {
                    "send-message": this.$form.attr("data-send-message-endpoint")
                })
            },
            submitForm: function (event) {
                var data = this.$form.serializeHash(),
                    self = this;
                this.$filterForm && _.extend(data, this.$filterForm.serializeHash()), this.$messageSubmit.button("loading"), util.API.formSubmit(this.$form, event, {
                    data: data,
                    endpoint: this.ENDPOINTS["send-message"],
                    redirects: !0,
                    ajaxOptions: {
                        error: function () {
                            self.$messageSubmit.button("reset")
                        },
                        success: function (data) {
                            if (this.onSuccess(data), data.chat && require(["chat/views"], function (chat) {
                                chat.postInit(data.chat)
                            }), data.content) {
                                $(".new-subject-message-form").modal("hide");
                                var $content = $(data.content);
                                $("body").append($content);
                                var form = new profiles.NewPasswordForm({
                                    el: $content,
                                    ajaxOptions: {
                                        success: function () {
                                            location.href = data.nextURL
                                        }.bind(this)
                                    }
                                });
                                return form.show(), void 0
                            }
                            return data.nextURL ? (location.href = data.nextURL, void 0) : (this.trigger("sendMessage"), this.$(".js-send-button").fadeOut("fast"), this.$toolbar.hide(), this.$("textarea").replaceWith($("<p/>").addClass("green").html("Your message has been sent!")), void 0)
                        }.bind(this)
                    }
                })
            },
            onSuccess: function () {}
        }),
        ModalMessageForm = MessageForm.extend({
            events: {
                "click .message-submit": "submitForm",
                keypress: "handleKeypress"
            },
            handleKeypress: function (e) {
                util.isEnterKey(e) && this.submitForm(e)
            },
            initialize: function (options) {
                MessageForm.prototype.initialize.call(this, options), this.$form = this.$("form"), this.updateEndpoints(options)
            },
            show: function () {
                this.$el.modal("show"), this.onShow()
            },
            onShow: function () {},
            hide: function () {
                this.$el.modal("hide"), this.onHide()
            },
            onHide: function () {}
        });
    return {
        MessageForm: MessageForm,
        ModalMessageForm: ModalMessageForm
    }
}), define("experts/views", ["chat/constants", "experts/messages", "profiles/views", "schedule/meet-now", "events", "config", "util"], function (constants, messages, profiles, meetNow, events, config, util) {
    var $ffmSubject = $("#ffm-subject-container"),
        spinnerOptions = {
            lines: 13,
            length: 4,
            width: 2,
            radius: 5,
            rotate: 20,
            color: "#000",
            speed: 1,
            trail: 97,
            shadow: !1,
            hwaccel: !0,
            top: "auto",
            left: "auto"
        },
        mobileFilters = function () {
            $(".expert-metadata .tools").on("click", function () {
                return $(this).toggleClass("open"), $(".tutor-filters .filters").toggleClass("open"), !1
            }), $("#filter-close").on("click", function () {
                return $(".expert-metadata .tools").removeClass("open"), $(".tutor-filters .filters").removeClass("open"), !1
            })
        },
        TagFieldView = Backbone.Marionette.View.extend({
            events: {
                "keypress .tag-input": "inputKeypressHandler",
                "click .remove-tag": "removeTag"
            },
            ui: {
                tagInput: ".tag-input",
                tagField: ".tag-field",
                tagList: ".tag-list"
            },
            liTemplate: _.template('<div class="tag"><i class="remove-tag"></i><span class="tag-word"><%- name %></span></div>'),
            initialize: function (opts) {
                this.$filterForm = opts.$filterForm, this.bindUIElements(), this.reset()
            },
            empty: function () {
                this.words = [], this.ui.tagList.empty()
            },
            loadExisting: function () {
                this.ui.tagField.find("option").each(function (i, elem) {
                    this.addWord($(elem).val())
                }.bind(this))
            },
            reset: function (options) {
                this.empty(), this.loadExisting(), _.each(options || [], function (option) {
                    this.addWord(option)
                }.bind(this))
            },
            addWord: function (word) {
                return this.words.push(word), this.ui.tagList.append($(this.liTemplate({
                    name: word
                }))), word
            },
            addNewWord: function (newWord) {
                if (-1 === $.inArray(newWord, this.words)) {
                    var word = this.addWord(newWord);
                    $("<option>").attr({
                        value: word,
                        selected: "selected"
                    }).appendTo(this.ui.tagField)
                }
            },
            inputKeypressHandler: function (e) {
                var $target = $(e.target);
                $target.removeClass("error"), util.isEnterKey(e) && this.submitTagField($target)
            },
            submitTagField: function ($input) {
                this.addNewWord(_.escape($input.val())), this.updateForm($input)
            },
            updateForm: function ($input) {
                $input.val(""), this.$filterForm.trigger("change")
            },
            removeTag: function (e) {
                var $keyword = $(e.target).parent(),
                    word = $keyword.find(".tag-word").html();
                this.words = _.without(this.words, word), $keyword.remove(), this.ui.tagField.find('option[value="' + word + '"]').remove(), this.$filterForm.trigger("change")
            }
        }),
        SubjectFieldView = TagFieldView.extend({
            ui: {
                select: "#id_filter-subjects"
            },
            initialize: function (options) {
                this.bindUIElements(), this.$filterForm = options.$filterForm, this.subjectID = options.subjectID, this.words = [], this.tags = _.map(this.ui.select.find(":selected"), function (s) {
                    return {
                        label: s.innerHTML,
                        value: parseInt(s.value)
                    }
                }), this.subjectID && (this.tags = _.reject(this.tags, function (t) {
                    return t.value == this.subjectID
                }.bind(this)), this.words.push(parseInt(this.subjectID))), this.source = _.map(this.ui.select[0], function (s) {
                    return {
                        label: s.innerHTML,
                        value: parseInt(s.value)
                    }
                }), this.noResultsLabel = "No Results", this.noResults = !1, this.lowercaseSource = _.map(this.source, function (s) {
                    return {
                        label: s.label.toLowerCase(),
                        value: s.value
                    }
                }), this.ui.tagInput.autocomplete({
                    focus: this.updateInput.bind(this),
                    select: this.updateInput.bind(this),
                    close: function (e) {
                        this.submitTagField($(e.target))
                    }.bind(this),
                    source: function (request, response) {
                        var results = $.ui.autocomplete.filter(this.source, request.term);
                        0 === results.length ? (results = [this.noResultsLabel], this.noResults = !0) : this.noResults = !1, response(results)
                    }.bind(this)
                });
                var self = this;
                this.ui.select.change(function () {
                    self.empty(), self.ui.select.find("option:selected").each(function (idx, option) {
                        self.addNewWord($(option).text())
                    })
                }), this.loadExisting()
            },
            submitTagField: function ($input) {
                this.addNewWord(_.escape($input.val())) && (this.ui.tagInput.autocomplete("close"), this.updateForm($input))
            },
            inputKeypressHandler: function (e) {
                util.isEnterKey(e) && (this.ui.tagInput.autocomplete("search"), this.noResults && util.flashClass(this.ui.tagInput, "autocomplete-error", 300)), TagFieldView.prototype.inputKeypressHandler.call(this, e)
            },
            removeTag: function (e) {
                var $keyword = $(e.target).parent(),
                    word = $keyword.find(".tag-word").html();
                $keyword.remove();
                var id = this.getTag(word).value;
                id && (this.words = _.without(this.words, id), this.ui.select.find(_.sprintf("[value=%s]", id)).prop("selected", !1), this.$filterForm.trigger("change"))
            },
            getTag: function (tag) {
                return tag = _.findWhere(this.lowercaseSource, {
                    label: tag.toLowerCase()
                }), tag ? _.findWhere(this.source, {
                    value: tag.value
                }) : !1
            },
            addNewWord: function (newWord) {
                if (newWord = this.getTag(newWord), !newWord) return !1;
                if (-1 !== $.inArray(newWord.value, this.words)) return !0;
                var id = this.addWord(newWord);
                return this.ui.select.find(_.sprintf("[value=%s]", id)).prop("selected", !0), !0
            },
            addWord: function (word) {
                return this.words.push(word.value), this.ui.tagList.append($(this.liTemplate({
                    name: word.label
                }))), word.value
            },
            updateInput: function (e, ui) {
                return ui.item.label === this.noResultsLabel ? !1 : (e.preventDefault(), this.ui.tagInput.val(ui.item.label), void 0)
            },
            loadExisting: function () {
                _.each(this.tags, function (t) {
                    this.addWord(t)
                }.bind(this))
            }
        }),
        FFMSubjectView = Backbone.View.extend({
            events: {
                "change select": "selectChangeHandler"
            },
            initialize: function (opts) {
                var $select = this.$("select");
                $select.chosen(), this.ffmSubjectView = new ChosenSelectView({
                    el: $select
                }), this.$filterForm = opts.$filterForm, this.$filterSubject = this.$filterForm.find("#id_filter-subjects"), this.filterSubjectView = new ChosenSelectView({
                    el: this.$filterSubject
                }), this.$filterSubject.change(this.filterSubjectChangeHandler.bind(this))
            },
            selectChangeHandler: function (e) {
                this.filterSubjectView.update($(e.target).val()), this.filterSubjectView.$el.change()
            },
            filterSubjectChangeHandler: function (e) {
                var $filterSubject = $(e.target);
                $filterSubject.val() ? 1 === ($filterSubject.val() || []).length && this.ffmSubjectView.update($filterSubject.val()) : this.$el.slideDown()
            }
        }),
        ChosenSelectView = Backbone.View.extend({
            update: function (value) {
                this.$el.val(value).trigger("liszt:updated")
            }
        }),
        ResultsPageView = Backbone.Marionette.View.extend({
            ui: {
                experts: ".experts",
                expertMessage: ".expert-message",
                expertMetadata: ".expert-metadata-container",
                filterAvailableNow: "input[name$=available_now]",
                meetNow: ".meet-now-link",
                noAvailableNow: ".no-available-now",
                pagination: ".pagination-container",
                spinner: ".no-available-now .spinner",
                startLessonButton: ".start-lesson"
            },
            opacityLow: "0.5",
            opacityHigh: "1",
            events: {
                "click @ui.startLessonButton": "startLesson",
                "click .match-me": "ffmClickHandler",
                "click @ui.expertMessage": "openChatBox",
                "click @ui.meetNow": "startMeetNow",
                "click @ui.filterAvailableNow": "availableNowFilterToggled"
            },
            initialize: function (opts) {
                this.bindUIElements(), this.onlineCount = 0, this.keywordView = opts.keywordView, this.subjectView = opts.subjectView, this.$filterForm = opts.$filterForm, this.$filterForm.change(this.changeHandler.bind(this)), this.$filterSubjects = this.$filterForm.find("#id_filter-subjects"), this.$pageInput = this.$filterForm.find('input[name="p"]'), this.selectedSubjects = this.$filterSubjects.val() || [], this.$ffmButton = this.$(".match-me"), this.$ffmSignupButton = this.$("#ffm-signup-form button"), this.ffmNextURL = this.$ffmButton.attr("data-href"), this.slNextURL = this.ui.startLessonButton.attr("data-href"), this.spinner = new window.Spinner(spinnerOptions), this.spinnerEl = document.getElementById("loading-spinner"), this.popoverVisible = !1, this.setupPaginationClickHandler(), 0 === Number(this.$(".online-count").html()) && (this.$ffmButton.addClass("disabled"), this.$ffmSignupButton.addClass("disabled")), this.lastQuery = this.$filterForm.serialize(), this.setupHistory(), this.updateFFMMatchingText(), meetNow.setupPage(this.ui.experts)
            },
            setupHistory: function () {
                this.regex = new RegExp("^[?]?(.*)$", "i"), Backbone.history.route(this.regex, this.updateForm.bind(this))
            },
            updateForm: function (fragment) {
                var serializedData = this.regex.exec(fragment)[1];
                serializedData !== this.lastQuery && (this.lastQuery = serializedData, this.getResults(serializedData))
            },
            startLesson: function (event) {
                var $clicked = $(event.target),
                    $subjectsField = this.$filterForm.find(".subject-filter");
                if (!config.isOnlineTutors && this.$filterForm.find("[name=filter-subjects]").val()) {
                    $subjectsField.removeClass("error autocomplete-error"), $clicked.parents(".no-available-now").exists() ? this.ui.spinner.fadeIn("fast") : $clicked.button("loading");
                    var isAvailableNow = this.ui.filterAvailableNow.prop("checked");
                    this.ui.filterAvailableNow.prop("checked", !1);
                    var querystring = this.$filterForm.serialize();
                    this.ui.filterAvailableNow.prop("checked", isAvailableNow), window.location.href = this.slNextURL + "?" + querystring
                } else this.showSubjectPopover($clicked);
                return !1
            },
            showSubjectPopover: function ($clicked) {
                if ($clicked.find(".js-popover-content").exists()) {
                    $clicked.hasClass("js-popover") || ($clicked.addClass("js-popover").data({
                        trigger: "manual",
                        placement: "bottom"
                    }), util.attachPopovers($clicked));
                    var hidePopover = function () {
                        this.popoverVisible = !1, $clicked.removeClass("active").popover("hide")
                    }.bind(this);
                    if (this.popoverVisible) return hidePopover(), void 0;
                    $clicked.addClass("active").popover("show"), this.popoverVisible = !0;
                    var $popover = $clicked.data("popover").tip(),
                        $select = $popover.find("select"),
                        $options = this.$filterSubjects.find("option").clone();
                    $popover.css("width", null), $popover.addClass("start-lesson-popover"), $popover.on("click", "button", function (event) {
                        var subject = $select.val();
                        if (!subject) {
                            var $chosen = $("#" + $select.prop("id") + "_chzn");
                            return $chosen.addClass("error").focus(), !1
                        }
                        $popover.find(".spinner").show();
                        var href = $(event.target).data("href");
                        return window.location.assign(href + "?filter-subjects=" + subject), !1
                    }), $select.append($options), $select.val(this.$filterSubjects.val()), $select.chosen(), util.triggerOnGlobalClick(function ($target) {
                        return $target.closest($popover).exists()
                    }, hidePopover, {
                        ignoreCallback: function ($target) {
                            return $target.closest($clicked).exists()
                        }
                    })
                }
            },
            ffmClickHandler: function () {
                var url, ffmSubjectVal;
                if (this.$ffmButton.hasClass("disabled")) return !1;
                if (!this.selectedSubjects.length) {
                    if (ffmSubjectVal = $ffmSubject.find("select").val(), !ffmSubjectVal) return !1;
                    this.$filterForm.find("#id_filter-subjects").val(ffmSubjectVal)
                }
                return url = this.ffmNextURL + "?" + this.$filterForm.serialize(), window.location.href = url, !1
            },
            updateFFMMatchingText: function () {
                var text, id, $matching = $("#subject-info-online-now .matching"),
                    $gender = this.$filterForm.find('input[type="radio"][name="filter-gender"]:checked'),
                    $keyword = this.$filterForm.find("#id_filter-keyword"),
                    $subject = this.$filterForm.find("#id_filter-subjects");
                $gender.val() || $keyword.val() ? $matching.html("matching").show() : 1 === ($subject.val() || []).length ? (id = $subject.val()[0], text = this.$("#id_filter-subjects").find('option[value="' + id + '"]').html(), $matching.html(text).show()) : $matching.hide()
            },
            changeHandler: function () {
                this.navigate(!0)
            },
            navigate: function (resetPage) {
                resetPage && this.setPage(1);
                var serialized = this.$filterForm.serialize();
                Backbone.history.navigate("?" + serialized, {
                    trigger: !0
                })
            },
            getResults: function (serializedData, retried) {
                this.ui.experts.css("opacity", this.opacityLow), this.spinner.spin(this.spinnerEl);
                var spinnerOff = function () {
                    this.ui.experts.css("opacity", this.opacityHigh), this.spinner.stop()
                }.bind(this);
                util.API.get("/online-tutors/", {
                    data: serializedData,
                    checkDataForDoubleSubmit: !0,
                    success: function () {
                        this.getResultsSuccess.apply(this, arguments), spinnerOff()
                    }.bind(this),
                    error: function (data, xhr) {
                        return 400 == xhr.status && data.error && "page-num" == data.error && !retried ? this.getResults(serializedData.replace(/p=\d+&?/g, ""), !0) : (spinnerOff(), void 0)
                    }.bind(this)
                })
            },
            getResultsSuccess: function (data) {
                var onlineCount = Number(data.onlineCount),
                    availableNow = this.ui.filterAvailableNow.prop("checked");
                0 !== onlineCount ? (this.onlineCount = data.onlineCount, this.$(".online-count").html(data.onlineCount), this.$(".online-count-zero").hide(), this.$(".online-count-non-zero").show(), 1 === onlineCount ? (this.$(".online-count-plural").hide(), this.$(".online-count-singular").show()) : (this.$(".online-count-singular").hide(), this.$(".online-count-plural").show()), this.$ffmButton.removeClass("disabled"), this.$ffmSignupButton.removeClass("disabled")) : availableNow || (this.onlineCount = 0, this.$(".online-count-singular").hide(), this.$(".online-count-plural").show(), this.$(".online-count").html("0"), this.$(".online-count-zero").show(), this.$(".online-count-non-zero").hide(), this.$ffmButton.addClass("disabled"), this.$ffmSignupButton.addClass("disabled")), availableNow && this._trackAvailableNowFilterChange(!0, onlineCount), 0 === onlineCount && availableNow ? (this.onlineCount || (this.onlineCount = this.$(".js-tutor-count").text()), this.ui.noAvailableNow.find(".online-count").text(this.onlineCount), this.ui.noAvailableNow.slideDown()) : (this.ui.noAvailableNow.hide(), this.ui.experts.html(data.expertsHTML), this.ui.pagination.html(data.paginationHTML), this.ui.expertMetadata.html(data.expertMetadataHTML), this.setupPaginationClickHandler(), this.updateFFMMatchingText(), util.attachPopovers(this.ui.experts), meetNow.setupPage(this.ui.experts)), mobileFilters()
            },
            setupPaginationClickHandler: function () {
                var self = this;
                this.ui.pagination.on("click", "a", function () {
                    var match = $(this).attr("href").match(/\d+$/),
                        page = match ? match[0] : 1;
                    return self.setPage(page), self.navigate(), self.scrollTop(), !1
                })
            },
            setPage: function (page) {
                this.$pageInput.val(page)
            },
            scrollTop: function () {
                var top = this.$(".expert-metadata-container").offset().top;
                top = top - 10 - $("#header").height(), $("html, body").animate({
                    scrollTop: 0
                }, 150)
            },
            openChatBox: function (event) {
                openChatBox(event, "tutor-list")
            },
            startMeetNow: function (event) {
                startMeetNow(event, "subject-page")
            },
            availableNowFilterToggled: function () {
                var checked = this.ui.filterAvailableNow.prop("checked");
                checked || this._trackAvailableNowFilterChange(!1, 0)
            },
            _trackAvailableNowFilterChange: function (state, count) {
                events.create(events.EVENT.AVAILABLE_NOW_SEARCH_CHANGED, {
                    state: state,
                    authed: config.isAuthenticated,
                    count: count
                })
            }
        }),
        ProfileSidebar = Backbone.Marionette.View.extend({
            el: "#public-profile-sidebar",
            ui: {
                scheduleForm: ".schedule-with-tutor-form",
                messageButton: ".js-send-button",
                openScheduleFormButton: "#open-schedule-form",
                openScheduleFormButtonLabel: "#open-schedule-form span",
                removeProposalLink: ".remove-proposal",
                messageToolbar: "#sendmessage-toolbar",
                subjectSelect: '[name="subject"]'
            },
            events: {
                "click #open-schedule-form": "openScheduleForm",
                "click .remove-proposal": "closeScheduleForm"
            },
            initialize: function (options) {
                this.formOpen = !1, this.bindUIElements(), this.listenTo(options.messageForm, "sendMessage", function () {
                    this.ui.openScheduleFormButton.hide()
                })
            },
            openScheduleForm: function () {
                return this.$el.removeClass("added-dimension"), this.ui.messageToolbar.hide(), this.ui.scheduleForm.show(), this.ui.subjectSelect.chosen(), !1
            },
            closeScheduleForm: function () {
                return this.$el.addClass("added-dimension"), this.ui.scheduleForm.hide(), this.ui.messageToolbar.show(), !1
            }
        }),
        openChatBox = function (event, context) {
            var $target = $(event.target),
                $cover = $target.closest(".expert-message-cover"),
                $expert = $target.closest(".expert-list-item"),
                $imgContainer = $expert.find(".expert-photo-container"),
                availability = $cover.data("chat-availability"),
                availableNow = $cover.data("chat-available-now");
            _(constants.AVAILABILITY).contains(availability) || (availability = constants.AVAILABILITY.OFFLINE), events.create(events.EVENT.MESSAGE_TUTOR, {
                context: context
            });
            var chatData = {
                id: $cover.data("chat-id"),
                urlID: $cover.data("chat-url"),
                gender: $cover.data("chat-gender"),
                name: $cover.data("chat-name"),
                photo: $imgContainer.find("img").attr("src"),
                role: constants.ROLE.TUTOR,
                availability: availability,
                availableNow: "1" == availableNow,
                isBusy: "1" == $cover.data("chat-busy")
            };
            Backbone.trigger("chat:open", chatData)
        },
        startMeetNow = function (event, context) {
            var $target = $(event.target),
                $cover = $target.closest(".expert-message-cover"),
                tutorID = $cover.data("chat-id"),
                tutorName = $cover.data("chat-name");
            meetNow.start(tutorID, tutorName, context, config.subjectID)
        };
    return {
        ResultsPageView: ResultsPageView,
        ProfileSidebar: ProfileSidebar,
        mobileFilters: mobileFilters,
        MessageForm: messages.MessageForm,
        ModalMessageForm: messages.ModalMessageForm,
        openChatBox: openChatBox,
        startMeetNow: startMeetNow,
        FFMSubjectView: FFMSubjectView,
        SubjectFieldView: SubjectFieldView,
        TagFieldView: TagFieldView
    }
}), define("add-card/views", ["util"], function (util) {
    var getCookie = function (name) {
            var cookieValue = null;
            if (document.cookie && "" !== document.cookie)
                for (var cookies = document.cookie.split(";"), i = 0; i < cookies.length; i++) {
                    var cookie = jQuery.trim(cookies[i]);
                    if (cookie.substring(0, name.length + 1) == name + "=") {
                        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                        break
                    }
                }
            return cookieValue
        },
        PageView = Backbone.View.extend({
            $form: null,
            stripePublishableKey: null,
            runDeclinedTransactionsURL: null,
            successURL: null,
            createStripeAccountURL: null,
            events: {
                "submit form": "formSubmit"
            },
            initialize: function (opts) {
                this.$form = opts.form, this.stripePublishableKey = opts.stripePublishableKey, this.runDeclinedTransactionsURL = opts.runDeclinedTransactionsURL, this.successURL = opts.successURL, this.createStripeAccountURL = opts.createStripeAccountURL, this.$form.find(".expiration_date_month").val(_.sprintf("%02d", (new Date).getMonth() + 1))
            },
            formSubmit: function () {
                return this.$form.find("button").prop("disabled") ? !1 : (this.$form.find("button").disable(), window.Stripe.setPublishableKey(this.stripePublishableKey), window.Stripe.createToken({
                    number: $(".card_number").val(),
                    cvc: $(".card_cvv").val(),
                    exp_month: $(".expiration_date_month").val(),
                    exp_year: $(".expiration_date_year").val()
                }, _.bind(this.stripeResponseHandler, this)), !1)
            },
            stripeResponseHandler: function (status, response) {
                if (response.error) return this.showError(response.error.message), void 0;
                var token = response.id,
                    inputStr = '<input id="stripeToken" type="hidden" name="stripeToken" value="%s">';
                this.$form.append(_.sprintf(inputStr, token)), this.createStripeAccount()
            },
            createStripeAccount: function () {
                util.API.post(this.createStripeAccountURL, {
                    data: this.$form.serialize(),
                    success: this.runDeclinedTrans.bind(this),
                    error: this.errorHandler.bind(this)
                })
            },
            runDeclinedTrans: function () {
                util.API.post(this.runDeclinedTransactionsURL, {
                    data: {
                        csrfmiddlewaretoken: getCookie("csrftoken")
                    },
                    success: function () {
                        window.location.href = this.successURL
                    }.bind(this),
                    error: this.errorHandler.bind(this)
                })
            },
            errorHandler: function (data) {
                return data.error ? (this.showError(data.error), void 0) : (window.showErrorCatchall(), void 0)
            },
            showError: function (error) {
                this.$form.find("button").removeClass("disabled").removeAttr("disabled"), this.$form.find("input").val("").blur(), this.$form.find("input#stripeToken").remove(), this.$el.find(".payment-errors").html(error).show()
            }
        });
    return {
        PageView: PageView
    }
}), define("reviews/views", ["util"], function (util) {
    var REVIEW_STATUS = {
            NONE: 1,
            HELPFUL: 2,
            UNHELPFUL: 3
        },
        LessonReview = Backbone.Marionette.View.extend({
            events: {
                "click .thumbs-up": "toggleThumbsUp",
                "click .thumbs-down": "toggleThumbsDown",
                "click .submit-review": "submitReview",
                "click .submit-tech-feedback": "submitTechFeedback",
                "click .show-tech-feedback": "showTechFeedback",
                "click .show-review": "showReview"
            },
            ui: {
                reviewContainer: "#submit-review-form",
                reviewForm: "#review-form",
                reviewButton: ".submit-review",
                helpfulContainer: ".helpful-container",
                unhelpfulContainer: ".unhelpful-container",
                textContainer: ".text-container",
                helpful: "[name=is_helpful]",
                reviewTextarea: "#review-form textarea",
                reviewCounter: "#review-form .counter span",
                technicalDisclaimer: ".technical-disclaimer",
                feedbackContainer: "#tech-feedback-form",
                feedbackForm: "#feedback-form",
                feedbackButton: ".submit-tech-feedback",
                feedbackTextContainer: ".feedback-text-container",
                hasFeedback: ".has-feedback",
                feedbackTextarea: "#feedback-form textarea",
                feedbackCounter: "#feedback-form .counter span",
                feedbackError: ".feedback-error",
                formErrors: ".form-error",
                lessonCode: "[name=lessonCode]",
                tutorName: ".tutor-name",
                thumbsUp: ".thumbs-up",
                thumbsDown: ".thumbs-down"
            },
            initialize: function () {
                this.bindUIElements()
            },
            setupCounters: function () {
                this.reviewCounter || (this.reviewCounter = new util.TextCounter({
                    el: this.ui.reviewTextarea,
                    $counter: this.ui.reviewCounter,
                    limit: 1e3,
                    callback: function (avail) {
                        this.ui.reviewButton[avail >= 0 ? "enable" : "disable"]()
                    }.bind(this)
                })), this.feedbackCounter || (this.feedbackCounter = new util.TextCounter({
                    el: this.ui.feedbackTextarea,
                    $counter: this.ui.feedbackCounter,
                    limit: 1e3,
                    callback: function (avail) {
                        this.ui.feedbackButton[avail >= 0 ? "enable" : "disable"]()
                    }.bind(this)
                }))
            },
            toggleThumbsUp: function () {
                this.setInactive(), this.ui.thumbsUp.hasClass("active") ? this.ui.thumbsUp.removeClass("active") : (this.ui.thumbsUp.addClass("active"), this.ui.helpful.val(REVIEW_STATUS.HELPFUL), this.ui.helpfulContainer.show(), this.ui.textContainer.show())
            },
            toggleThumbsDown: function () {
                this.setInactive(), this.ui.thumbsDown.hasClass("active") ? this.ui.thumbsDown.removeClass("active") : (this.ui.thumbsDown.addClass("active"), this.ui.helpful.val(REVIEW_STATUS.UNHELPFUL), this.ui.unhelpfulContainer.show(), this.ui.technicalDisclaimer.show(), this.ui.textContainer.show())
            },
            setInactive: function () {
                this.ui.helpful.val(REVIEW_STATUS.NONE), this.ui.thumbsUp.removeClass("active"), this.ui.thumbsDown.removeClass("active"), this.ui.textContainer.hide(), this.ui.helpfulContainer.hide(), this.ui.unhelpfulContainer.hide(), this.ui.technicalDisclaimer.hide(), this.ui.formErrors.hide(), this.ui.reviewTextarea.removeClass("error").val(""), this.ui.feedbackTextarea.val("")
            },
            showReview: function () {
                return this.ui.feedbackContainer.hide(), this.ui.reviewContainer.show(), !1
            },
            showTechFeedback: function () {
                return this.ui.reviewContainer.hide(), this.ui.feedbackContainer.show(), !1
            },
            submitReview: function (event) {
                return event.preventDefault(), this.reviewCounter.getAvailableCharacters() < 0 ? !1 : (this.ui.reviewTextarea.removeClass("error"), util.API.formSubmit(this.ui.reviewForm, event, {
                    $btn: this.ui.reviewButton,
                    endpoint: this.ui.reviewForm.attr("action"),
                    redirects: !0,
                    ajaxOptions: {
                        csrf: !0,
                        success: this.submitReviewSuccess.bind(this),
                        error: function (data) {
                            data.errors && data.errors.__all__ && this.ui.reviewTextarea.addClass("error")
                        }.bind(this)
                    }
                }), void 0)
            },
            submitReviewSuccess: function (data) {
                data.isHelpful === !1 ? window.location.reload() : window.location.href = data.redirect
            },
            submitTechFeedback: function (event) {
                return event.preventDefault(), _.isBlank(this.ui.feedbackTextarea.val()) ? (this.ui.feedbackTextarea.addClass("error"), this.ui.feedbackError.show(), !1) : this.feedbackCounter.getAvailableCharacters() < 0 ? !1 : (this.ui.feedbackTextarea.removeClass("error"), this.ui.feedbackError.hide(), util.API.formSubmit(this.ui.feedbackForm, event, {
                    $btn: this.ui.feedbackButton,
                    endpoint: this.ui.feedbackForm.attr("action"),
                    redirects: !0,
                    ajaxOptions: {
                        csrf: !0,
                        success: this.submitFeedbackSuccess.bind(this)
                    }
                }), void 0)
            },
            submitFeedbackSuccess: function () {
                window.location.href = "/"
            }
        }),
        LessonReviewModal = LessonReview.extend({
            show: function (lessonCode, tutorName, $reviewCell) {
                this.setupCounters(), this.ui.reviewForm[0].reset(), this.ui.reviewButton.button("reset"), this.ui.feedbackForm[0].reset(), this.ui.feedbackButton.button("reset"), this.ui.lessonCode.val(lessonCode), this.ui.tutorName.text(tutorName), this.setInactive(), this.$reviewCell = $reviewCell, this.ui.feedbackTextContainer.show(), this.ui.hasFeedback.hide(), this.$el.modal("show")
            },
            submitReviewSuccess: function (data) {
                var $span = $("<span/>");
                data.isHelpful === !0 ? $span.addClass("thumbsup") : data.isHelpful === !1 ? $span.addClass("thumbs-down") : $span.text("Written feedback"), $span.attr("title", data.text || "No written feedback"), this.$reviewCell.empty().append($span), this.$el.modal("hide"), data.isHelpful === !0 && "/" != data.redirect && (window.location.href = data.redirect)
            },
            submitFeedbackSuccess: function () {
                this.$reviewCell.empty().text("Tech Fail"), this.$el.modal("hide")
            }
        });
    return {
        LessonReview: LessonReview,
        LessonReviewModal: LessonReviewModal
    }
}), define("paperboard/tools", ["util"], function (util) {
    return function (paper, project) {
        var keyEvents = ["onKeyDown", "onKeyUp"],
            toolEvents = ["onMouseDrag", "onMouseUp", "onMouseDown", "onMouseMove", "onMouseEnter", "onMouseLeave", "onClick", "onDoubleClick", "onActivate", "onDeactivate"].concat(keyEvents),
            SMALLBUTNOTZERO = 1e-5,
            CANVAS_CONSTRAINT_OFFSET = 5,
            Tool = Backbone.NoSync.Model.extend({
                initialize: function () {
                    this.tool = new paper.Tool, this.tool.minDistance = 1, this.tool.erasable = this.canErase(), this.tool.selectable = this.canSelect(), this.tool.name = this.getName(), this.tool.useShadow = this.useShadow(), this.set("id", this.getName()), this.smoothing = !0, this.shadow = null, this.callbacks = {};
                    var self = this;
                    _.each(toolEvents, function (toolEvent) {
                        self.callbacks[toolEvent] = [];
                        var isKeyEvent = _(keyEvents).contains(toolEvent);
                        self.tool[toolEvent] = function (event) {
                            if (!isKeyEvent || project.view.element == event.event.target) {
                                var last = null;
                                return _.each(self.callbacks[toolEvent], function (callback) {
                                    last = callback(event, last)
                                }), last
                            }
                        }
                    }), this.onActivate(function () {
                        self.trigger("activated")
                    }), this.onDeactivate(function () {
                        self.trigger("deactivated")
                    }), this.init(), this.createsItems() && this.setupForCreatingItems()
                },
                init: function () {},
                createItem: function (event, dragging) {
                    return event = null, dragging = null, null
                },
                isActive: function () {
                    return this.tool.isActive()
                },
                activate: function () {
                    this.tool.activate()
                },
                deactivate: function () {
                    this.tool.deactivate()
                },
                createsItems: function () {
                    return !0
                },
                canSelect: function () {
                    return !0
                },
                canErase: function () {
                    return !0
                },
                useShadow: function () {
                    return !0
                },
                autoAdd: function () {
                    return !0
                },
                canSingleClick: function () {
                    return !1
                },
                getName: function () {
                    return "tool"
                },
                setupForCreatingItems: function () {
                    var lastDragEvent, self = this,
                        onDrag = function (event) {
                            var item = self.createItem(event, !0);
                            return self.useShadow() && (self.shadow && self.shadow.remove(), self.shadow = item, self.shadow.opacity = .75), lastDragEvent = event, item
                        };
                    if (this.onMouseDrag(onDrag), self.useShadow()) {
                        var shiftKey = !1,
                            ctrlKey = !1,
                            altKey = !1,
                            onKeyPress = function (event) {
                                !lastDragEvent || event.event.shiftKey == shiftKey && event.event.ctrlKey == ctrlKey && event.event.altKey == altKey || (shiftKey = event.event.shiftKey, ctrlKey = event.event.ctrlKey, altKey = event.event.altKey, lastDragEvent.event = event.event, onDrag(lastDragEvent))
                            };
                        this.onKeyDown(onKeyPress), this.onKeyUp(onKeyPress)
                    }
                    this.onMouseUp(function (event, item) {
                        self.useShadow() && self.shadow && self.shadow.remove(), lastDragEvent = null, (self.canSingleClick() || !event.point.equals(event.downPoint)) && (item = item || self.createItem(event), item._itemType = self.tool.name, item.setClippable(self.tool.erasable), item.setSelectable(self.tool.selectable), item.setLocked(!self.tool.selectable), self.postCreate(item), self.autoAdd() && self.trigger("action.add", item), self.trigger("action.completed", item))
                    })
                },
                postCreate: function (item) {
                    item = null
                }
            });
        _.each(toolEvents, function (toolEvent) {
            Tool.prototype[toolEvent] = function (callback) {
                this.callbacks[toolEvent].push(callback)
            }
        });
        var ShapeTool = Tool.extend({
                canErase: function () {
                    return !1
                }
            }),
            CircleTool = ShapeTool.extend({
                createItem: function (event) {
                    var vector = event.point.subtract(event.downPoint),
                        center = event.downPoint;
                    if (event.event.shiftKey) {
                        var max = Math.max(vector.x, vector.y);
                        vector = new paper.Point(max, max)
                    }
                    event.event.ctrlKey && (center = center.subtract(vector.length / 2), vector = vector.multiply(2));
                    var circle = new paper.Path.Ellipse({
                        point: center,
                        size: vector
                    });
                    return event.event.altKey && circle.rotate(vector.angle), circle
                },
                getName: function () {
                    return "circle"
                }
            }),
            RectangleTool = ShapeTool.extend({
                createItem: function (event) {
                    var firstPoint = event.downPoint,
                        otherPoint = event.point,
                        vector = otherPoint.subtract(firstPoint);
                    if (event.event.shiftKey) {
                        var max = Math.max(vector.x, vector.y);
                        otherPoint = firstPoint.add(new paper.Point(max, max))
                    }
                    event.event.ctrlKey && (firstPoint = firstPoint.subtract(otherPoint.subtract(firstPoint)));
                    var rectangle = new paper.Path.Rectangle(firstPoint, otherPoint);
                    return event.event.altKey && rectangle.rotate(vector.angle), rectangle
                },
                getName: function () {
                    return "rectangle"
                }
            }),
            TriangleTool = ShapeTool.extend({
                createItem: function (event) {
                    var triangle, vector = event.point.subtract(event.downPoint);
                    if (event.event.shiftKey) {
                        var half = vector.length / 2,
                            center = event.downPoint.add(new paper.Point(half, half));
                        event.event.ctrlKey && (center = event.downPoint), triangle = new paper.Path.RegularPolygon(center, 3, half)
                    } else {
                        var middlePoint = vector.divide(2),
                            firstPoint = new paper.Point(event.downPoint.x + middlePoint.x, event.downPoint.y),
                            secondPoint = event.point,
                            thirdPoint = new paper.Point(event.downPoint.x, secondPoint.y);
                        event.event.ctrlKey && (firstPoint = new paper.Point(event.downPoint.x, event.downPoint.y - (secondPoint.y - event.downPoint.y)), thirdPoint = new paper.Point(event.downPoint.x - (secondPoint.x - event.downPoint.x), secondPoint.y)), triangle = new paper.Path([firstPoint, secondPoint, thirdPoint]), triangle.closed = !0
                    }
                    return triangle
                },
                getName: function () {
                    return "triangle"
                }
            }),
            RightTrangleTool = ShapeTool.extend({
                createItem: function (event) {
                    var firstPoint = event.downPoint,
                        secondPoint = event.point;
                    event.event.shiftKey && (firstPoint.angle = 45, secondPoint.angle = 45);
                    var thirdPoint = new paper.Point(firstPoint.x, secondPoint.y),
                        triangle = new paper.Path([firstPoint, secondPoint, thirdPoint]);
                    return triangle.closed = !0, triangle
                },
                getName: function () {
                    return "rightTriangle"
                }
            }),
            LineTool = ShapeTool.extend({
                SNAP_ANGLE: 15,
                createItem: function (event) {
                    var startPoint = event.downPoint,
                        endPoint = event.point,
                        vector = endPoint.subtract(startPoint);
                    if (event.event.shiftKey) {
                        var offset = vector.angle % this.SNAP_ANGLE,
                            add = offset >= this.SNAP_ANGLE / 2;
                        add ? vector.angle += this.SNAP_ANGLE - offset : vector.angle -= offset, endPoint = startPoint.add(vector)
                    }
                    var path = new paper.Path([startPoint, endPoint]);
                    return this.smoothing && path.smooth(), path
                },
                getName: function () {
                    return "line"
                }
            }),
            LineArrowTool = LineTool.extend({
                ANGLE: 155,
                LENGTH: 15,
                POINT: 10,
                createItem: function (event) {
                    var path = LineTool.prototype.createItem.call(this, event);
                    return this.createArrow(path)
                },
                createArrow: function (line) {
                    var start = line.firstSegment.point,
                        end = line.lastSegment.point,
                        vector = end.subtract(start),
                        arrowVector = vector.normalize(this.LENGTH),
                        arrowPoint = vector.normalize(this.POINT),
                        lPoint = end.add(arrowVector.rotate(-this.ANGLE)),
                        middle = end.subtract(arrowPoint),
                        rPoint = end.add(arrowVector.rotate(this.ANGLE));
                    return line.remove(), line = new paper.Path([middle, lPoint, end, rPoint, middle, start]), line.fillColor = project.currentStyle.strokeColor, line.closed = !0, line
                },
                getName: function () {
                    return "arrow"
                }
            }),
            LineDoubleArrowTool = LineArrowTool.extend({
                createArrow: function (line) {
                    line = LineArrowTool.prototype.createArrow.call(this, line), line.closed = !1;
                    var start = line.segments[line.segments.length - 1].point,
                        end = line.segments[line.segments.length - 2].point,
                        vector = start.subtract(end),
                        arrowVector = vector.normalize(this.LENGTH),
                        arrowPoint = vector.normalize(this.POINT),
                        lPoint = start.add(arrowVector.rotate(-this.ANGLE)),
                        middle = start.subtract(arrowPoint),
                        rPoint = start.add(arrowVector.rotate(this.ANGLE));
                    return line.addSegments([middle, lPoint, start, rPoint, middle]), line.fillColor = project.currentStyle.strokeColor, line.closed = !0, line
                },
                getName: function () {
                    return "doubleArrow"
                }
            }),
            PenTool = Tool.extend({
                init: function () {
                    var path, self = this;
                    this.onMouseDown(function (event) {
                        return self.tool.minDistance = Math.floor(project.currentStyle.strokeWidth / 4), path = new paper.Path, path.strokeCap = "round", path.add(event.point), path.add(event.point.add(.001, 0)), path
                    }), this.onMouseDrag(function (event) {
                        path.add(event.point)
                    }), this.onMouseUp(function () {
                        return self.smoothing && path.simplify(2), path
                    })
                },
                canSelect: function () {
                    return !1
                },
                canSingleClick: function () {
                    return !0
                },
                useShadow: function () {
                    return !1
                },
                getName: function () {
                    return "pen"
                }
            }),
            EraserTool = PenTool.extend({
                init: function () {
                    PenTool.prototype.init.call(this), this.tool.minDistance = 1, this.smoothing = !1, this.onMouseDown(function (event, path) {
                        path.setClipMask(!0), path.setStrokeColor(1, 1, 1)
                    })
                },
                canErase: function () {
                    return !1
                },
                getName: function () {
                    return "eraser"
                }
            }),
            TextTool = Tool.extend({
                createItem: function (event, dragging) {
                    var bounds = RectangleTool.prototype.createItem.apply(this, arguments);
                    if (bounds.strokeWidth = 2, bounds.strokeColor = "#000", bounds.fillColor = null, dragging) return bounds;
                    bounds.remove();
                    var text = new paper.AreaText({
                        segments: bounds.segments,
                        closed: !0
                    });
                    return text.fillColor = new paper.Color(0, 0, 0, 0), text.text.strokeColor = null, text
                },
                postCreate: function (item) {
                    item.setColorStyle(project.currentStyle.strokeColor), item.setFontStyle(project.currentStyle.strokeWidth)
                },
                canErase: function () {
                    return !1
                },
                autoAdd: function () {
                    return !1
                },
                getName: function () {
                    return "text"
                }
            }),
            SelectorTool = Tool.extend({
                init: function () {
                    var hitResult, activeItem, activeClone, moveItem, prevMousePoint, self = this,
                        dragging = !1,
                        ctrlKey = !1,
                        hitOptions = {
                            type: "PathItem",
                            segments: !0,
                            fill: !0,
                            stroke: !0,
                            handles: !1,
                            bounds: !0,
                            boundingBox: !0,
                            tolerance: 10
                        };
                    this.cloneItem = function (item) {
                        return activeClone = item, activeItem = item.clone(), activeItem.select(), activeClone.remove(), self.trigger("active.item", activeItem), activeItem._itemSelected = ctrlKey, activeItem._boundsSelected = !ctrlKey, hitResult && _.each(activeItem.segments, function (segment) {
                            segment.equals(hitResult.segment) && (hitResult.segment = segment)
                        }), activeItem
                    }, this.setActiveItem = function (item) {
                        activeItem = item
                    }, this.getActiveItem = function () {
                        return activeItem
                    }, this.deactivate = function () {
                        project.deselectAll(), hitResult = activeItem = activeClone = prevMousePoint = null, ctrlKey = dragging = !1
                    }, this.onDeactivate(this.deactivate), this.onMouseDown(function (event) {
                        hitResult = project.activeLayer.hitTest(event.point, hitOptions), activeItem = activeClone = moveItem = null, hitResult ? (activeItem = hitResult.item, dragging = !0, self.trigger("active.item", activeItem)) : (project.deselectAll(), self.trigger("active.item", null))
                    }), this.onMouseMove(function (event) {
                        if (!dragging) {
                            self.trigger("cursor.change", null);
                            var hr = project.activeLayer.hitTest(event.point, hitOptions);
                            hr ? (moveItem != hr.item && (project.deselectAll(), moveItem = hr.item, moveItem.select()), ctrlKey ? moveItem.selectCurves() : moveItem.deselectCurves(), moveItem._itemSelected != ctrlKey && (moveItem._itemSelected = ctrlKey, moveItem._boundsSelected = !ctrlKey, project.view.draw()), "bounds" == hr.type || "boundingEdge" == hr.type ? self.trigger("cursor.change", hr.name) : "handle-in" == hr.type || "handle-out" == hr.type || "segment" == hr.type ? self.trigger("cursor.change", null) : self.trigger("cursor.change", "move")) : (moveItem && (project.deselectAll(), moveItem = null), activeItem && (activeItem.select(), ctrlKey && activeItem.selectCurves()))
                        }
                    });
                    var enforceResizeConstraints = function (sides, event) {
                        var dx = event.delta.x,
                            dy = event.delta.y,
                            bounds = activeItem.getBounds(),
                            minWidth = 0,
                            minHeight = 0;
                        "text" == activeItem._itemType && (minWidth = minHeight = 1.2 * parseInt(activeItem.text.fontSize, 10)), _.each(sides, function (side) {
                            switch (side) {
                            case "right":
                                bounds.width - dx > minWidth && event.point.x < bounds.x + bounds.width ? (bounds.x += dx, bounds.width -= dx) : (bounds.x += bounds.width - minWidth, bounds.width = minWidth + SMALLBUTNOTZERO);
                                break;
                            case "bottom":
                                bounds.height - dy > minHeight && event.point.y < bounds.y + bounds.height ? (bounds.y += dy, bounds.height -= dy) : (bounds.y += bounds.height - minHeight, bounds.height = minHeight + SMALLBUTNOTZERO);
                                break;
                            case "left":
                                bounds.width + dx > minWidth && event.point.x > bounds.x ? bounds.width += dx : bounds.width = minWidth + SMALLBUTNOTZERO;
                                break;
                            case "top":
                                bounds.height + dy > minHeight && event.point.y > bounds.y ? bounds.height += dy : bounds.height = minHeight + SMALLBUTNOTZERO
                            }
                        })
                    };
                    this.onMouseDrag(function (event) {
                        if (dragging)
                            if (activeClone || self.cloneItem(hitResult.item), $.inArray(hitResult.type, ["stroke", "fill", "boundingBox"]) > -1) {
                                var canvasBounds = paper.view.bounds.clone(),
                                    dx = event.delta.x,
                                    dy = event.delta.y,
                                    shapeOffsetW = activeItem.bounds.width / 2,
                                    shapeOffsetH = activeItem.bounds.height / 2,
                                    maxX = canvasBounds.width + shapeOffsetW - CANVAS_CONSTRAINT_OFFSET,
                                    minX = CANVAS_CONSTRAINT_OFFSET,
                                    maxY = canvasBounds.height + shapeOffsetH - CANVAS_CONSTRAINT_OFFSET,
                                    minY = CANVAS_CONSTRAINT_OFFSET;
                                activeItem.position.x + dx > maxX || event.point.x > maxX + dx && 0 > dx ? activeItem.position.x = maxX : activeItem.position.x + shapeOffsetW + dx < minX || event.point.x + shapeOffsetW + dx < minX && dx > 0 ? activeItem.position.x = -shapeOffsetW + minX : activeItem.position.x += dx, activeItem.position.y + dy > maxY || event.point.y > maxY + dy && 0 > dy ? activeItem.position.y = maxY : activeItem.position.y + shapeOffsetH + dy < minY || event.point.y + shapeOffsetH + dy < minY && dy > 0 ? activeItem.position.y = -shapeOffsetH + minY : activeItem.position.y += dy
                            } else if ("bounds" == hitResult.type || "boundingEdge" == hitResult.type) switch (hitResult.name) {
                        case "top-left":
                            enforceResizeConstraints(["right", "bottom"], event);
                            break;
                        case "top":
                        case "top-center":
                            enforceResizeConstraints(["bottom"], event);
                            break;
                        case "top-right":
                            enforceResizeConstraints(["left", "bottom"], event);
                            break;
                        case "right":
                        case "right-center":
                            enforceResizeConstraints(["left"], event);
                            break;
                        case "bottom-right":
                            enforceResizeConstraints(["top", "left"], event);
                            break;
                        case "bottom":
                        case "bottom-center":
                            enforceResizeConstraints(["top"], event);
                            break;
                        case "bottom-left":
                            enforceResizeConstraints(["top", "right"], event);
                            break;
                        case "left":
                        case "left-center":
                            enforceResizeConstraints(["right"], event)
                        } else {
                            var segment = hitResult.segment;
                            if (event.event.ctrlKey) {
                                segment.select();
                                var param;
                                switch (hitResult.type) {
                                case "segment":
                                    param = "point";
                                    break;
                                case "handle-in":
                                    param = "handleIn";
                                    break;
                                case "handle-out":
                                    param = "handleOut";
                                    break;
                                default:
                                    return
                                }
                                segment[param] = segment[param].add(event.delta)
                            } else {
                                var regular = segment.point.subtract(activeItem.position),
                                    modified = event.point.subtract(activeItem.position);
                                if (event.event.shiftKey) {
                                    var regularRound = regular.round(),
                                        modifiedRound = modified.round(),
                                        xScale = 0 !== regularRound.x ? modifiedRound.x / regularRound.x : 1,
                                        yScale = 0 !== regularRound.y ? modifiedRound.y / regularRound.y : 1;
                                    activeItem.scale(xScale || 1, yScale || 1)
                                } else {
                                    var scale = modified.length / regular.length;
                                    activeItem.scale(scale)
                                }
                            }
                        }
                    }), this.onMouseUp(function (event) {
                        if (dragging = !1, hitResult = null, activeItem)
                            if (activeClone && !event.point.equals(event.downPoint)) self.trigger("action.add", activeItem, activeClone), self.trigger(activeItem._itemType + ".edited", activeItem, activeClone);
                            else if (prevMousePoint && prevMousePoint.equals(event.point)) {
                            var triggerEvent = activeItem._itemType + ".double-click";
                            self.trigger(triggerEvent, activeItem, activeClone)
                        }
                        self.trigger("cursor.change", null), prevMousePoint = event.downPoint.equals(event.point) ? event.downPoint.clone() : null
                    }), this.onKeyUp(function (event) {
                        event.event.ctrlKey != ctrlKey && (ctrlKey = event.event.ctrlKey, hitOptions.bounds = hitOptions.boundingBox = !0, hitOptions.handles = !1, activeItem && activeItem.deselectCurves()), dragging || (activeItem && activeClone && !activeItem.bounds.equals(activeClone.bounds) && (self.trigger("action.add", activeItem, activeClone), self.trigger(activeItem._itemType + ".edited", activeItem, activeClone)), activeClone = null)
                    }), this.onKeyDown(function (event) {
                        if (event.event.ctrlKey != ctrlKey && (ctrlKey = event.event.ctrlKey, hitOptions.bounds = hitOptions.boundingBox = !1, hitOptions.handles = !0, activeItem && activeItem.selectCurves()), !activeItem) {
                            switch (hitResult = activeItem = activeClone = null, event.event.keyCode) {
                            case util.Event.KEY_BACK_SPACE:
                            case util.Event.KEY_DELETE:
                                return event.preventDefault(), event.stopPropagation(), !1
                            }
                            return !0
                        }
                        activeClone || self.cloneItem(activeItem);
                        var items = [activeItem];
                        switch (event.event.keyCode) {
                        case util.Event.KEY_UP:
                            _.each(items, function (item) {
                                item.position.y -= 1
                            });
                            break;
                        case util.Event.KEY_DOWN:
                            _.each(items, function (item) {
                                item.position.y += 1
                            });
                            break;
                        case util.Event.KEY_LEFT:
                            _.each(items, function (item) {
                                item.position.x -= 1
                            });
                            break;
                        case util.Event.KEY_RIGHT:
                            _.each(items, function (item) {
                                item.position.x += 1
                            });
                            break;
                        case util.Event.KEY_PERIOD:
                            _.each(items, function (item) {
                                item.rotate(1)
                            });
                            break;
                        case util.Event.KEY_COMMA:
                            _.each(items, function (item) {
                                item.rotate(-1)
                            });
                            break;
                        case util.Event.KEY_EQUAL_SIGN:
                            _.each(items, function (item) {
                                item.scale(1.01)
                            });
                            break;
                        case util.Event.KEY_DASH:
                            _.each(items, function (item) {
                                item.scale(1 / 1.01)
                            });
                            break;
                        case util.Event.KEY_BACK_SPACE:
                        case util.Event.KEY_DELETE:
                            _.each(items, function (item) {
                                item.remove(), self.trigger("action.add", null, item)
                            }), self.deactivate();
                            break;
                        default:
                            return !0
                        }
                        event.preventDefault()
                    })
                },
                setActiveItemColor: function (color) {
                    var item = this.getActiveItem();
                    if (item) {
                        var existing = "text" == item._itemType ? item.text.fillColor.toHex(!0) : item.strokeColor.toHex(!0);
                        if (color != "#" + existing) {
                            var clone = item.clone();
                            item.remove(), "text" == clone._itemType ? clone.setColorStyle(color) : clone.strokeColor = color, this.trigger("action.add", clone, item), this.setActiveItem(clone), project.view.draw()
                        }
                    }
                },
                setActiveItemSize: function (width) {
                    var item = this.getActiveItem();
                    if (item) {
                        var existing = "text" == item._itemType ? parseInt(item.text.fontSize) : item.strokeWidth;
                        if (width != existing) {
                            var clone = item.clone();
                            item.remove(), "text" == clone._itemType ? clone.setFontStyle(width) : clone.strokeWidth = width, this.trigger("action.add", clone, item), this.setActiveItem(clone), project.view.draw()
                        }
                    }
                },
                useShadow: function () {
                    return !1
                },
                createsItems: function () {
                    return !1
                },
                getName: function () {
                    return "selector"
                }
            }),
            ToolCollection = Backbone.NoSync.Collection.extend({
                model: Tool
            });
        return {
            Tool: Tool,
            createTools: function () {
                return new ToolCollection([new CircleTool, new RectangleTool, new TriangleTool, new RightTrangleTool, new LineTool, new LineArrowTool, new LineDoubleArrowTool, new PenTool, new EraserTool, new TextTool, new SelectorTool])
            }
        }
    }
}), define("paperboard/views", ["paper", "paperboard/manager", "util"], function (paperBase, paperManager, util) {
    var getViews = function (paper, project) {
            var StrokeWidths = Backbone.Marionette.View.extend({
                    MODES: {
                        PEN: 1,
                        ERASER: 2,
                        TEXT: 3
                    },
                    events: {
                        "click div": "change"
                    },
                    ui: {
                        stroke1: ".stroke-width-1",
                        stroke2: ".stroke-width-2",
                        stroke3: ".stroke-width-3",
                        stroke4: ".stroke-width-4",
                        stroke5: ".stroke-width-5",
                        strokes: "div"
                    },
                    penSizes: {
                        1: 2,
                        2: 4,
                        3: 8,
                        4: 16
                    },
                    eraserSizes: {
                        1: 2,
                        2: 8,
                        3: 16,
                        4: 32
                    },
                    textSizes: {
                        1: 12,
                        2: 20,
                        3: 32,
                        4: 64
                    },
                    initialize: function () {
                        this.bindUIElements(), this.enable(), this.mode = this.MODES.PEN, this.update(this.ui.stroke1)
                    },
                    enable: function () {
                        this.enabled = !0, this.active && this.active.addClass("active"), this.ui.strokes.removeClass("disabled")
                    },
                    disable: function () {
                        this.enabled = !1, this.active && this.active.removeClass("active"), this.ui.strokes.addClass("disabled")
                    },
                    change: function (event) {
                        this.update($(event.target))
                    },
                    update: function ($stroke) {
                        if (this.enabled) {
                            var previous = this.active;
                            previous && previous.removeClass("active"), this.active = $stroke, this.active.addClass("active");
                            var stroke = $stroke.data("stroke"),
                                strokeWidth = this.penSizes[stroke];
                            switch (this.mode) {
                            case this.MODES.ERASER:
                                strokeWidth = this.eraserSizes[stroke];
                                break;
                            case this.MODES.TEXT:
                                strokeWidth = this.textSizes[stroke]
                            }
                            project.currentStyle.strokeWidth = strokeWidth, previous && previous[0] != $stroke[0] && this.trigger("updated", strokeWidth)
                        }
                    },
                    updatePen: function (strokeWidth) {
                        this.mode = this.MODES.PEN;
                        var stroke = _(this.penSizes).invert()[strokeWidth],
                            $ui = this.ui["stroke" + stroke];
                        this.update($ui)
                    },
                    updateText: function (strokeWidth) {
                        this.setText(!0);
                        var stroke = _(this.textSizes).invert()[strokeWidth],
                            $ui = this.ui["stroke" + stroke];
                        this.update($ui)
                    },
                    setText: function (enable) {
                        this.mode = enable ? this.MODES.TEXT : this.MODES.PEN, this.active && this.update(this.active), this.$el[enable ? "addClass" : "removeClass"]("text")
                    },
                    setEraser: function (enable) {
                        this.mode = enable ? this.MODES.ERASER : this.MODES.PEN, enable && this.update(this.ui.stroke4)
                    }
                }),
                StrokeColors = Backbone.Marionette.View.extend({
                    events: {
                        "click div": "change"
                    },
                    ui: {
                        "#000": ".color-black",
                        "#fb0000": ".color-red",
                        "#007ee8": ".color-blue",
                        "#2dc100": ".color-green",
                        colors: "div"
                    },
                    initialize: function () {
                        this.bindUIElements(), this.enable(), this.update("#000")
                    },
                    enable: function () {
                        this.enabled = !0, this.active && this.active.addClass("active"), this.ui.colors.removeClass("disabled")
                    },
                    disable: function () {
                        this.enabled = !1, this.active && this.active.removeClass("active"), this.ui.colors.addClass("disabled")
                    },
                    change: function (event) {
                        var $target = $(event.target);
                        this.update("#" + $target.data("color"))
                    },
                    update: function (color) {
                        if (this.enabled && project.currentStyle.strokeColor != color) {
                            var previous = this.active;
                            previous && previous.removeClass("active"), color in this.ui && (this.active = this.ui[color], this.active.addClass("active"), project.currentStyle.strokeColor = color, previous && previous[0] != this.ui[color][0] && this.trigger("updated", color))
                        }
                    }
                }),
                Tool = Backbone.Marionette.View.extend({
                    events: {
                        click: "activate"
                    },
                    modelEvents: {
                        activated: "_activated",
                        deactivated: "_deactivated",
                        "action.completed": "actionCompleted"
                    },
                    initialize: function (options) {
                        this.bindUIElements(), this.$canvas = options.$canvas, this.strokeWidths = options.strokeWidths, this.strokeColors = options.strokeColors, this.selector = options.selector, this.originalStyle = null, this.stopClickPropagation = !1, this.init(options)
                    },
                    init: function (options) {
                        return options
                    },
                    activate: function (event) {
                        this.stopClickPropagation && event && event.stopPropagation(), this.model.isActive() && this.selector ? this.selector.activate() : this.model.activate()
                    },
                    _activated: function () {
                        this.$el.addClass("active"), this.enableCursor(this.getCursorClass()), this.trigger("activated", this), this.activated()
                    },
                    activated: function () {},
                    deactivate: function () {
                        this.model.deactivate()
                    },
                    _deactivated: function () {
                        this.$el.removeClass("active"), this.disableCursor(this.getCursorClass()), this.deactivated()
                    },
                    deactivated: function () {},
                    actionCompleted: function () {},
                    saveCurrentStyle: function () {
                        this.originalStyle = {
                            strokeWidth: this.strokeWidths.active,
                            strokeWidthMode: this.strokeWidths.mode,
                            strokeColor: project.currentStyle.strokeColor
                        }
                    },
                    restoreCurrentStyle: function () {
                        this.originalStyle && (this.strokeWidths.mode = this.originalStyle.strokeWidthMode, this.originalStyle.strokeWidth && this.strokeWidths.update(this.originalStyle.strokeWidth), this.strokeColors.update(this.originalStyle.strokeColor), this.originalStyle = null)
                    },
                    getCursorClass: function () {
                        return null
                    },
                    enableCursor: function (cursorClass) {
                        cursorClass && this.$canvas.addClass(cursorClass)
                    },
                    disableCursor: function (cursorClass) {
                        cursorClass && this.$canvas.removeClass(cursorClass)
                    }
                }),
                PenTool = Tool.extend({
                    getCursorClass: function () {
                        return "pen"
                    }
                }),
                EraserTool = Tool.extend({
                    getCursorClass: function () {
                        return "eraser"
                    },
                    activated: function () {
                        this.saveCurrentStyle(), this.strokeWidths.setEraser(!0), this.strokeColors.disable()
                    },
                    deactivated: function () {
                        this.restoreCurrentStyle(), this.strokeWidths.setEraser(!1), this.strokeColors.enable()
                    }
                }),
                ShapeTool = Tool.extend({
                    init: function (options) {
                        this.$shapesButton = options.$shapesButton, this.$shapesContainer = options.$shapesContainer, this.stopClickPropagation = !0
                    },
                    getCursorClass: function () {
                        return "shape"
                    },
                    activated: function () {
                        this.$shapesButton.addClass("active"), this.$shapesContainer.show()
                    },
                    deactivated: function () {
                        this.$shapesButton.data("clicked") || (this.$shapesButton.removeClass("active"), this.$shapesContainer.hide())
                    },
                    actionCompleted: function (item) {
                        this.selector.activate(), this.selector.setActiveItem(item), item.select()
                    }
                }),
                TextTool = Tool.extend({
                    init: function () {
                        this.selector.on("model:text.double-click", this.editText.bind(this)), this.strokeColors.on("updated", this.colorUpdated.bind(this)), this.strokeWidths.on("updated", this.widthUpdated.bind(this)), this.activeItem = null, this.activeClone = null, this.hasClone = !1, this.$textarea = null
                    },
                    getCursorClass: function () {
                        return "text"
                    },
                    clearActive: function () {
                        this.activeItem = this.activeClone = null, this.hasClone = !1, this.$textarea && (this.$textarea.remove(), this.$textarea = null)
                    },
                    activated: function () {
                        this.clearActive(), this.saveCurrentStyle(), this.strokeWidths.updateText(20)
                    },
                    deactivated: function () {
                        this.clearActive(), this.restoreCurrentStyle()
                    },
                    colorUpdated: function (color) {
                        this.model.isActive() && this.activeItem && (this.activeItem.setColorStyle(color), this.$textarea.css({
                            color: color
                        }), project.view.draw())
                    },
                    widthUpdated: function (strokeWidth) {
                        if (this.model.isActive() && this.activeItem) {
                            var height = 1.2 * strokeWidth;
                            this.activeItem.setFontStyle(strokeWidth, height), this.$textarea.css({
                                "font-size": strokeWidth + "px",
                                "line-height": height + "px"
                            }), project.view.draw()
                        }
                    },
                    actionCompleted: function (item) {
                        this.editText(item)
                    },
                    editText: function (item, clone) {
                        this.model.isActive() || this.activate(), this.activeItem && this.removeTextarea();
                        var self = this,
                            bounds = item.bounds,
                            offset = this.$canvas.offset(),
                            content = item.text.content || "",
                            hasClone = !!clone;
                        hasClone || (clone = item, item = this.selector.model.cloneItem(item));
                        var $textarea = $("<textarea>").addClass("text-point").css({
                            top: bounds.y + offset.top,
                            left: bounds.x + offset.left,
                            width: bounds.width,
                            height: bounds.height
                        }).on("keyup", function (event) {
                            event.keyCode == util.Event.KEY_ESCAPE && self.removeTextarea(!0)
                        }).val(content);
                        $("body").append($textarea), $textarea.focus();
                        var fontSize = project.currentStyle.strokeWidth,
                            lineHeight = 1.2 * fontSize,
                            color = project.currentStyle.strokeColor;
                        _.isBlank(content) || (fontSize = parseInt(item.text.fontSize, 10), lineHeight = 1.2 * fontSize, color = "#" + item.text.fillColor.toHex(!0), this.strokeWidths.updateText(fontSize), this.strokeColors.update(color)), $textarea.css({
                            color: color,
                            "font-size": fontSize + "px",
                            "line-height": lineHeight + "px"
                        }), $textarea.selectRange($textarea.val().length), item.setFontStyle(fontSize, lineHeight, $textarea.css("font-family")), item.setColorStyle(color), item.visible = !1, project.view.draw(), this.$textarea = $textarea, this.activeItem = item, this.activeClone = clone, this.hasClone = hasClone;
                        var attachClickHandler = function () {
                            $("html").one("click.areatext", function (event) {
                                event.target === $textarea[0] || $(event.target).closest(".ignore-text-click").exists() ? ($textarea.focus(), attachClickHandler()) : self.removeTextarea(!0)
                            })
                        };
                        _.delay(attachClickHandler, 100)
                    },
                    removeTextarea: function (activateSelector) {
                        if (this.$textarea && this.activeItem) {
                            var item = this.activeItem,
                                clone = this.activeClone,
                                hasClone = this.hasClone,
                                content = item.text.content,
                                newContent = this.$textarea.val();
                            this.clearActive(), item.visible = !0, _.isBlank(newContent) ? (item.remove(), hasClone && this.model.trigger("action.add", null, clone)) : content != newContent && (item.text.content = newContent, clone._itemID ? this.model.trigger("action.add", item, clone) : this.model.trigger("action.add", item, null), activateSelector ? (this.selector.activate(), this.selector.setActiveItem(item)) : item.deselect()), project.view.draw(), $("html").off("click.areatext")
                        }
                    }
                }),
                SelectorTool = Tool.extend({
                    modelEvents: {
                        "cursor.change": "changeCursor",
                        "active.item": "setActiveItem"
                    },
                    init: function () {
                        this.model.on("all", function () {
                            var args = Array.prototype.slice.call(arguments);
                            args[0] = "model:" + args[0], this.trigger.apply(this, args)
                        }.bind(this)), this.strokeColors.on("updated", this.colorUpdated.bind(this)), this.strokeWidths.on("updated", this.widthUpdated.bind(this)), this.currentCursor = null
                    },
                    activated: function () {
                        this.model.getActiveItem() || (this.strokeColors.disable(), this.strokeWidths.disable())
                    },
                    deactivated: function () {
                        this.strokeColors.enable(), this.strokeWidths.enable(), this.strokeWidths.setText(!1)
                    },
                    setActiveItem: function (item) {
                        item ? (this.model.setActiveItem(item), item.select(), project.view.draw(), this.strokeColors.enable(), this.strokeWidths.enable(), "text" == item._itemType ? (this.strokeWidths.updateText(parseInt(item.text.fontSize)), this.strokeColors.update("#" + item.text.fillColor.toHex(!0))) : (this.strokeWidths.setText(!1), this.strokeWidths.updatePen(item.strokeWidth), this.strokeColors.update("#" + item.strokeColor.toHex(!0)))) : (this.activated(), this.strokeWidths.setText(!1))
                    },
                    getCursorClass: function () {
                        return this.currentCursor
                    },
                    changeCursor: function (cursor) {
                        this.disableCursor(this.getCursorClass()), this.enableCursor(cursor)
                    },
                    enableCursor: function (className) {
                        this.currentCursor = className, Tool.prototype.enableCursor.call(this, className)
                    },
                    disableCursor: function (className) {
                        this.currentCursor = null, Tool.prototype.disableCursor.call(this, className)
                    },
                    colorUpdated: function (color) {
                        this.model.isActive() && this.model.setActiveItemColor(color)
                    },
                    widthUpdated: function (width) {
                        this.model.isActive() && this.model.setActiveItemSize(width)
                    }
                }),
                Pagination = Backbone.View.extend({
                    _paginationTemplate: '<li class="active"><a href="javascript://" data-layerindex="<%= layerindex %>"><%= pagenumber %></a></li>',
                    events: {
                        "click ul a": "navigateLayer",
                        "click .new-page": "newPage"
                    },
                    initialize: function () {
                        this.$list = this.$("ul"), this.$newPage = this.$(".new-page"), this.paginationTemplate = _.template(this._paginationTemplate)
                    },
                    readOnly: function () {
                        this.$newPage.hide()
                    },
                    getPages: function () {
                        return this.$list.children()
                    },
                    getPage: function (number) {
                        return this.getPages().eq(number - 1)
                    },
                    navigateLayer: function (event) {
                        event.target = $(event.target).closest("a").first(), this.trigger("navigate", event)
                    },
                    newPage: function (event) {
                        this.trigger("newPage", event)
                    },
                    addNewPage: function (number) {
                        this.getPages().removeClass("active");
                        var html = this.paginationTemplate({
                            pagenumber: number,
                            layerindex: 2 * number - 1
                        });
                        this.$list.append(html)
                    },
                    activatePage: function (number) {
                        var $pages = this.getPages();
                        $pages.removeClass("active"), $pages.eq(number - 1).addClass("active")
                    },
                    empty: function () {
                        this.$list.empty()
                    }
                }),
                Options = Backbone.View.extend({
                    events: {
                        "change .smoothing input": "toggleSmoothing",
                        "click #grid-dropdown a.grid": "toggleGridBackground",
                        "click .grid-state-axes": "toggleAxesBackground"
                    },
                    initialize: function (options) {
                        this.paperboard = options.paperboard
                    },
                    readOnly: function () {
                        this.$el.hide()
                    },
                    toggleSmoothing: function (event) {
                        var enable = $(event.target).is(":checked");
                        this.paperboard.tools.pen.model.smoothing = !!enable, this.paperboard.tools.eraser.model.smoothing = !!enable
                    },
                    toggleGridControl: function (toggle) {
                        var tooltipStr = "You cannot add a grid on top of an uploaded file.",
                            $gridControl = this.$("#grid-control"),
                            $gridButton = this.$("#grid-btn");
                        toggle ? ($gridControl.removeClass("disabled"), $gridControl.tooltip("destroy"), $gridButton.data("toggle", "dropdown").removeClass("disabled")) : ($gridControl.addClass("disabled"), $gridControl.tooltip({
                            title: tooltipStr
                        }), $gridButton.data("toggle", "").addClass("disabled"))
                    },
                    toggleGridBackground: function (event) {
                        event.preventDefault();
                        var $selectedLIElement = $(event.currentTarget).parent(),
                            backgroundStyle = $selectedLIElement.data("bg");
                        this.trigger("gridBackgroundChange", backgroundStyle)
                    },
                    toggleAxesBackground: function (event) {
                        event.preventDefault();
                        var $axesCheckbox = this.$(".icon-checkbox"),
                            hasAxes = $axesCheckbox.hasClass("checked");
                        this.trigger("toggleAxesBackground", !hasAxes)
                    },
                    updateBackgroundIndicatorWidget: function (backgroundStyle, hasAxes) {
                        var $selectedLIElement = this.$("li.grid-state-" + backgroundStyle);
                        $selectedLIElement.addClass("active").siblings().removeClass("active"), this._updateGridIndicator("none" !== backgroundStyle, hasAxes)
                    },
                    _updateGridIndicator: function (hasGrid, hasAxes) {
                        var $axesCheckbox = this.$(".icon-checkbox"),
                            $gridstate = this.$("i.grid-state");
                        $gridstate.removeClass().addClass("grid-state"), hasGrid && hasAxes ? ($axesCheckbox.addClass("checked"), $gridstate.addClass("grid-axes")) : !hasGrid && hasAxes ? ($axesCheckbox.addClass("checked"), $gridstate.addClass("grid-axes")) : hasGrid || hasAxes ? hasGrid && !hasAxes && ($axesCheckbox.removeClass("checked"), $gridstate.addClass("grid-on")) : ($axesCheckbox.removeClass("checked"), $gridstate.addClass("grid-off"))
                    }
                }),
                Paperboard = Backbone.Marionette.View.extend({
                    events: {
                        "click .action-undo": "undo",
                        "click .action-redo": "redo",
                        "click .action-erase-all": "eraseAll",
                        "click .action-new-page": "newBoardPage",
                        "click .tool-shapes": "toggleShapes",
                        "click .whiteboard-tools > div": "clickTool"
                    },
                    modelEvents: {
                        "undo.disabled": "disableUndo",
                        "undo.enabled": "enableUndo",
                        "redo.disabled": "disableRedo",
                        "redo.enabled": "enableRedo",
                        "layer.added": "setupLayer",
                        "layers.redraw": "redrawLayers",
                        "change.background": "updateBackgroundLayer"
                    },
                    ui: {
                        canvas: "#editor",
                        toolbar: "#toolbar",
                        editorContainer: "#editor-container",
                        imageContainer: "#image-container",
                        strokeWidths: ".whiteboard-stroke-widths",
                        strokeColors: ".whiteboard-stroke-colors",
                        undoButton: ".action-undo",
                        redoButton: ".action-redo",
                        shapesButton: ".tool-shapes",
                        shapesContainer: ".tool-shapes-container",
                        textTool: ".tool-text",
                        penTool: ".tool-pen",
                        eraserTool: ".tool-eraser",
                        rectangleTool: ".tool-rectangle",
                        circleTool: ".tool-circle",
                        triangleTool: ".tool-triangle",
                        rightTriangleTool: ".tool-right-triangle",
                        lineTool: ".tool-line",
                        arrowTool: ".tool-arrow",
                        doubleArrowTool: ".tool-double-arrow"
                    },
                    initialize: function (options) {
                        this.bindUIElements(), this.model.canUndo() || this.disableUndo(), this.model.canRedo() || this.disableRedo(), this.paper = paper, this.project = project, this.activeToolView = null, this.tools = {}, this.defaultSize = {
                            width: this.ui.canvas.width(),
                            height: this.ui.canvas.height()
                        }, this.ui.canvas.attr("tabindex", "0"), this.pagination = new Pagination({
                            el: options.$pagination
                        }), this.pagination.on("navigate", this.navigateLayer.bind(this)), this.pagination.on("newPage", this.newBoardPage.bind(this)), this.options = new Options({
                            el: options.$options,
                            paperboard: this
                        }), this.options.on("gridBackgroundChange", this.updateBackground.bind(this)), this.options.on("toggleAxesBackground", this.toggleAxesBackground.bind(this)), options.readOnly ? this.readOnly() : this.setupTools(), this.ui.editorContainer.on("scroll", function (event) {
                            var scrollTop = $(event.target).scrollTop();
                            this.ui.imageContainer.scrollTop(scrollTop), project.activeLayer.scrollTop = scrollTop
                        }.bind(this)), this.redrawLayers()
                    },
                    setupTools: function () {
                        this.strokeWidths = new StrokeWidths({
                            el: this.ui.strokeWidths
                        }), this.strokeColors = new StrokeColors({
                            el: this.ui.strokeColors
                        });
                        var options = {
                            $canvas: this.ui.canvas,
                            strokeWidths: this.strokeWidths,
                            strokeColors: this.strokeColors,
                            $shapesButton: this.ui.shapesButton,
                            $shapesContainer: this.ui.shapesContainer
                        };
                        options.selector = new SelectorTool(_.extend(options, {
                            model: this.model.tools.get("selector")
                        })), this.listenTo(options.selector, "activated", this.toolActivated);
                        var tools = {
                            pen: PenTool,
                            eraser: EraserTool,
                            text: TextTool,
                            rectangle: ShapeTool,
                            circle: ShapeTool,
                            triangle: ShapeTool,
                            rightTriangle: ShapeTool,
                            line: ShapeTool,
                            arrow: ShapeTool,
                            doubleArrow: ShapeTool
                        };
                        this.tools = {
                            selector: options.selector
                        }, _.each(tools, function (ToolView, toolName) {
                            var $el = this.ui[toolName + "Tool"],
                                model = this.model.tools.get(toolName);
                            this.tools[toolName] = new ToolView(_.extend(options, {
                                el: $el,
                                model: model
                            })), this.listenTo(this.tools[toolName], "activated", this.toolActivated)
                        }.bind(this)), this.tools.pen.activate(), this.ui.shapesButton.data("clicked", !1)
                    },
                    toolActivated: function (view) {
                        this.activeToolView = view, this.trigger("tool:activated", view)
                    },
                    readOnly: function () {
                        this.tools.selector && this.tools.selector.activate(), _.each(paper.tools, function (tool) {
                            tool.remove()
                        }), this.ui.toolbar.hide(), this.pagination.readOnly(), this.options.readOnly()
                    },
                    blur: function () {
                        this.tools.selector.deactivate(), this.model.draw(), this.ui.canvas.blur()
                    },
                    undo: function () {
                        this.model.undo()
                    },
                    disableUndo: function () {
                        this.ui.undoButton.addClass("disabled")
                    },
                    enableUndo: function () {
                        this.ui.undoButton.removeClass("disabled")
                    },
                    redo: function () {
                        this.model.redo()
                    },
                    disableRedo: function () {
                        this.ui.redoButton.addClass("disabled")
                    },
                    enableRedo: function () {
                        this.ui.redoButton.removeClass("disabled")
                    },
                    eraseAll: function () {
                        this.model.clear(this.tools.pen.model.getName())
                    },
                    hasContent: function () {
                        return project.activeLayer.children.length > 0 || project.activeLayer.$imageList.children().exists()
                    },
                    newBoardPage: function () {
                        this.model.addBoardPage()
                    },
                    updateBackground: function (style, updateUI) {
                        updateUI = _.isUndefined(updateUI) ? !0 : updateUI;
                        var foregroundLayer = project.activeLayer,
                            backgroundLayer = foregroundLayer._background;
                        backgroundLayer.activate(), project.activeLayer.removeChildren(), "none" !== style && this.model.trigger("background.drawgrid", "whiteboard-background-" + style), backgroundLayer._gridBackgroundStyle = style, backgroundLayer._hasAxesBackground && this.model.trigger("background.drawaxes"), updateUI && this.options.updateBackgroundIndicatorWidget(backgroundLayer._gridBackgroundStyle, backgroundLayer._hasAxesBackground), this.model.addBackgroundUpdateAction(backgroundLayer), foregroundLayer.activate()
                    },
                    toggleAxesBackground: function (toggle, updateUI) {
                        updateUI = _.isUndefined(updateUI) ? !0 : updateUI;
                        var foregroundLayer = project.activeLayer,
                            backgroundLayer = foregroundLayer._background;
                        if (backgroundLayer.activate(), toggle) this.model.trigger("background.drawaxes"), backgroundLayer._hasAxesBackground = !0;
                        else {
                            project.activeLayer.removeChildren();
                            var style = project.activeLayer._gridBackgroundStyle;
                            "none" !== style && this.model.trigger("background.drawgrid", "whiteboard-background-" + style), backgroundLayer._hasAxesBackground = !1
                        }
                        updateUI && this.options.updateBackgroundIndicatorWidget(backgroundLayer._gridBackgroundStyle, backgroundLayer._hasAxesBackground), this.model.addBackgroundUpdateAction(backgroundLayer), foregroundLayer.activate()
                    },
                    setupLayer: function (layer) {
                        this._navigateLayer(this.addLayerNumber(layer))
                    },
                    getPageNumber: function (layerIndex) {
                        return layerIndex = layerIndex || project.activeLayer._index, (layerIndex + 1) / 2
                    },
                    addLayerNumber: function (layer) {
                        var pageNumber = this.getPageNumber(layer._index);
                        if (this.pagination.getPage(pageNumber).exists()) layer.$imageList = this.ui.imageContainer.find(".image-layer-" + layer._index);
                        else {
                            this.pagination.addNewPage(pageNumber);
                            var $imageList = $(_.sprintf('<ul class="image-layer image-layer-%s"/>', pageNumber));
                            layer.$imageList = $imageList, this.ui.imageContainer.append($imageList)
                        }
                        return layer._index
                    },
                    redrawLayers: function () {
                        this.pagination.empty(), this.ui.imageContainer.empty();
                        var foregroundLayers = _.filter(project.layers, function (layer) {
                            return layer._background
                        });
                        _.each(foregroundLayers, this.addLayerNumber.bind(this)), this._navigateLayer(_(foregroundLayers).last()._index)
                    },
                    updateBackgroundLayer: function (backgroundLayerIndex, properties) {
                        var currentBackgroundIndex = project.activeLayer._background._index,
                            targetForegroundLayer = project.layers[backgroundLayerIndex + 1],
                            updateUI = currentBackgroundIndex === backgroundLayerIndex;
                        targetForegroundLayer.activate();
                        var style = properties.style || "none";
                        this.updateBackground(style, updateUI), this.toggleAxesBackground(properties.hasAxes, updateUI)
                    },
                    navigateLayer: function (event) {
                        var $target = $(event.target),
                            pageNum = parseInt($target.data("layerindex"), 10);
                        _.isNaN(pageNum) || this._navigateLayer(pageNum)
                    },
                    _navigateLayer: function (layerNum) {
                        var layer = this.model.changeLayer(layerNum);
                        if (layer) {
                            var pageNum = this.getPageNumber(layerNum);
                            this.pagination.activatePage(pageNum), this.options.updateBackgroundIndicatorWidget(layer._background._gridBackgroundStyle, layer._background._hasAxesBackground), this.ui.imageContainer.children().hide(), layer.$imageList.show(), layer.$imageList.children().exists() ? (this.options.toggleGridControl(!1), this.updateBackground("none")) : this.options.toggleGridControl(!0), this.resizeCanvas(layer.$imageList.width(), layer.$imageList.height());
                            var scrollTop = layer.scrollTop || 0;
                            this.ui.editorContainer.scrollTop(scrollTop), this.ui.imageContainer.scrollTop(scrollTop), this.trigger("changed:layer", pageNum)
                        }
                    },
                    clickTool: function (event) {
                        this.ui.shapesButton.data("clicked") && this.ui.shapesButton[0] != event.target && this.toggleShapes(!1)
                    },
                    toggleShapes: function (useSelector) {
                        var clicked = !this.ui.shapesButton.data("clicked");
                        this.ui.shapesButton.data("clicked", clicked), useSelector !== !1 && this.tools.selector.activate(), clicked ? (this.ui.shapesButton.addClass("active"), this.ui.shapesContainer.show(), this.strokeWidths.enable(), this.strokeColors.enable()) : (this.ui.shapesButton.removeClass("active"), this.ui.shapesContainer.hide())
                    },
                    resizeCanvas: function (width, height) {
                        width = this.defaultSize.width, height = height > this.defaultSize.height ? height : this.defaultSize.height, this.ui.canvas.prop("height", height).prop("width", width).css({
                            height: height + "px",
                            width: width + "px"
                        }), project.view.setViewSize(new paper.Size(width, height)), this.model.draw(), this.ui.editorContainer.css("overflow", "hidden").hide().css("overflow-x", "hidden").css("overflow-y", "auto").show(0)
                    }
                });
            return Paperboard
        },
        getPaperboardComponents = function (canvas) {
            var paper = paperBase.setup(canvas),
                manager = paperManager(paper, paper.project),
                Paperboard = getViews(paper, paper.project);
            return {
                paper: paper,
                project: paper.project,
                manager: manager,
                Paperboard: Paperboard
            }
        };
    return {
        getPaperboardComponents: getPaperboardComponents,
        init: function ($el, options, components) {
            components || (components = getPaperboardComponents($el.find("canvas").attr("id")));
            var paperboard = new components.Paperboard({
                el: $el,
                $pagination: options.$pagination,
                $options: options.$options,
                readOnly: !!options.readOnly,
                model: components.manager
            });
            return components.manager.draw(), paperboard
        }
    }
}), define("paperboard/manager", ["paperboard/tools"], function (paperTools) {
    var setup = function (paper, project, toolCollection) {
        var PaperboardItem = Backbone.NoSync.Model.extend({
            defaults: {
                type: "",
                layer: 0,
                revisions: null
            },
            initialize: function () {
                this.id || this.setID("_" + PaperboardItem._id++), this.set("revisions", []), this.currentRevision = 0
            },
            setID: function (id) {
                this.updateID(id), _.each(this.getRevisions(), function (item) {
                    item._itemID = id
                })
            },
            getType: function () {
                return this.get("type")
            },
            getLayerNumber: function () {
                return this.get("layer") || 0
            },
            getRevisions: function () {
                return this.get("revisions")
            },
            getLayer: function () {
                return project.layers[this.getLayerNumber()]
            },
            isLayer: function () {
                return "layer" == this.get("type")
            },
            isFile: function () {
                return "file" == this.get("type")
            },
            isBackground: function () {
                return "background" == this.get("type")
            },
            toJSON: function () {
                var revisions = [];
                return this.isFile() || this.isBackground() ? revisions.push(this.getRevisions()[0]) : _.each(this.getRevisions(), function (revision) {
                    revisions.push(revision.exportJSON({
                        asObject: !0,
                        excludeChildren: !0
                    }))
                }), {
                    id: this.id,
                    layer: this.getLayerNumber(),
                    type: this.getType(),
                    revisions: revisions
                }
            },
            parse: function (data) {
                this.set({
                    layer: data.layer,
                    type: data.type
                }), this.setID(data.id), _.each(data.revisions, function (revision) {
                    if (!this.isLayer()) {
                        var rev = this.parseRevision(revision);
                        this.addRevision(rev), !rev || this.isLayer() || this.isFile() || this.isBackground() || rev.remove()
                    }
                }.bind(this))
            },
            parseRevision: function (revision) {
                return !revision || this.isFile() || this.isLayer() || this.isBackground() ? revision : paper.Base.importJSON(revision)
            },
            addRevision: function (item, show) {
                this.getRevisions().push(item), !item || this.isFile() || this.isBackground() || (item._itemID = this.id, item._itemType = this.get("type"));
                var rev = this.getRevisions().length - 1;
                return show && this.showRevision(rev), rev
            },
            getRevision: function (revisionNum) {
                var revisions = this.getRevisions(),
                    len = revisions.length;
                return revisionNum = parseInt(revisionNum), len > 0 && revisionNum >= 0 && len > revisionNum ? revisions[revisionNum] : !1
            },
            removeRevision: function (revisionNum) {
                var rev = this.getRevision(revisionNum);
                if (rev !== !1) {
                    !rev || this.isFile() || this.isBackground() || rev.remove(), this.getRevisions().splice(revisionNum, 1);
                    var len = this.getRevisions().length;
                    this.currentRevision > len - 1 && (this.currentRevision = len - 1)
                }
            },
            hideRevisions: function () {
                _.each(this.getRevisions(), function (revision) {
                    _.isObject(revision) && revision.remove()
                })
            },
            _showRevision: function (revisionNum) {
                this.hideRevisions();
                var rev = this.getRevision(revisionNum);
                _.isObject(rev) && this.getLayer().addChild(rev), this.currentRevision = revisionNum
            },
            showRevision: function (revisionNum) {
                revisionNum >= this.currentRevision && this._showRevision(revisionNum)
            },
            showPreviousRevision: function (revisionNum) {
                revisionNum <= this.currentRevision && this._showRevision(revisionNum - 1)
            },
            getLastAction: function () {
                var revisions = this.getRevisions(),
                    type = PaperboardAction.ACTIONS.ADD,
                    last = _.last(revisions),
                    len = revisions.length;
                return len > 1 && !_.isUndefined(last) && (type = last ? PaperboardAction.ACTIONS.MODIFY : PaperboardAction.ACTIONS.REMOVE), this._getAction(type, len - 1)
            },
            _getAction: function (type, revisionNum) {
                var items = {};
                return items[this.id] = revisionNum, new PaperboardAction({
                    items: items,
                    type: type,
                    immutable: this.isLayer() || this.isFile() || this.isBackground()
                })
            }
        });
        PaperboardItem._id = 0;
        var PaperboardItemCollection = Backbone.NoSync.Collection.extend({
                model: PaperboardItem,
                parse: function (items) {
                    var models = _.map(items, function (item) {
                        var model = new PaperboardItem;
                        return model.parse(item), model
                    });
                    this.add(models)
                }
            }),
            Items = new PaperboardItemCollection,
            PaperboardAction = Backbone.NoSync.Model.extend({
                defaults: {
                    owner: null,
                    type: 0,
                    items: null,
                    immutable: !1
                },
                initialize: function () {
                    this.id || (this.id = "_" + PaperboardAction._id++)
                },
                canUndo: function () {
                    return !this.isImmutable() && this.collection && this.getOwner() == this.collection.user
                },
                getOwner: function () {
                    return this.get("owner")
                },
                getType: function () {
                    return this.get("type")
                },
                getItems: function () {
                    return this.get("items") || {}
                },
                setItems: function (items) {
                    this.set("items", items || {})
                },
                setImmutable: function (immutable) {
                    this.set("immutable", !!immutable)
                },
                isImmutable: function () {
                    return !!this.get("immutable")
                },
                getRevisions: function () {
                    return _.map(this.getItems(), function (revisionNum, itemID) {
                        var model = Items.get(itemID);
                        return {
                            revision: revisionNum,
                            model: model
                        }
                    })
                },
                toJSON: function () {
                    return {
                        id: this.id,
                        type: this.getType(),
                        owner: this.getOwner(),
                        items: this.getItems(),
                        immutable: this.isImmutable()
                    }
                },
                parse: function (data) {
                    this.set({
                        id: data.id,
                        type: data.type,
                        items: data.items,
                        owner: data.owner,
                        immutable: !!data.immutable
                    })
                },
                toSingleJSON: function (undone) {
                    var data = this.toJSON();
                    if (delete data.items, undone === !0) data.undone = !0;
                    else if (undone === !1) data.undone = !1;
                    else switch (this.getType()) {
                    case PaperboardAction.ACTIONS.ADD:
                    case PaperboardAction.ACTIONS.MODIFY:
                    case PaperboardAction.ACTIONS.REMOVE:
                        data.items = {}, _.each(this.getItems(), function (revision, itemID) {
                            var item = Items.get(itemID);
                            data.items[itemID] = {
                                type: item.getType(),
                                layer: item.getLayerNumber(),
                                data: item.getRevision(revision)
                            }
                        })
                    }
                    return data
                },
                fromSingleJSON: function (data) {
                    this.set({
                        id: data.id,
                        type: data.type,
                        owner: data.owner
                    });
                    var items = {};
                    _.each(data.items, function (itemData, itemID) {
                        var item = Items.get(itemID),
                            exists = !!item;
                        exists || (item = new PaperboardItem, item.parse({
                            id: itemID,
                            type: itemData.type,
                            layer: itemData.layer
                        }), Items.push(item));
                        var revision = item.parseRevision(itemData.data);
                        items[itemID] = item.addRevision(revision), item.isLayer() || item.isFile() || item.isBackground() ? this.set({
                            immutable: !0
                        }) : revision && _.has(revision, "remove") && revision.remove()
                    }.bind(this)), this.set({
                        items: items
                    })
                },
                "delete": function () {
                    this.destroy(), _.each(this.getItems(), function (revision, itemID) {
                        var item = Items.get(itemID);
                        item.removeRevision(revision), 0 === item.getRevisions().length && item.destroy()
                    })
                }
            });
        PaperboardAction._id = 0, PaperboardAction.ACTIONS = {
            ADD: 1,
            MODIFY: 2,
            REMOVE: 3,
            DELETE: 4
        };
        var PaperboardActionCollection = Backbone.NoSync.Collection.extend({
                model: PaperboardAction,
                parse: function (actions) {
                    var models = _.map(actions || [], function (action) {
                        var model = new PaperboardAction;
                        return model.parse(action), model
                    });
                    this.add(models)
                }
            }),
            BackgroundHandler = Backbone.NoSync.Model.extend({
                initialize: function (project) {
                    this.project = project
                },
                drawTiledBackground: function (tiledImageSelector) {
                    for (var TILESIZE = 80, viewportBounds = this.project.view.bounds, stepsX = parseInt(Math.ceil(viewportBounds.width / TILESIZE), 10) + 1, stepsY = parseInt(Math.ceil(viewportBounds.height / TILESIZE), 10) + 1, tiles = [], i = 0; stepsX > i; i++)
                        for (var j = 0; stepsY > j; j++) {
                            var tile = new paper.Raster(tiledImageSelector);
                            tile.position.x = i * TILESIZE, tile.position.y = j * TILESIZE, tile.setSelectable(!1), tile.setLocked(!0), tiles.push(tile)
                        }
                    project.view.draw()
                },
                drawAxesBackground: function () {
                    var viewportBounds = this.project.view.bounds,
                        height = viewportBounds.height + .5,
                        width = viewportBounds.width + .5,
                        PADDING = 29,
                        items = [];
                    items = items.concat(this._drawArrowedAxe(0 + PADDING, Math.ceil(height / 2), width - PADDING, Math.ceil(height / 2))), items = items.concat(this._drawArrowedAxe(Math.ceil(width / 2), 0 + PADDING, Math.ceil(width / 2), height - PADDING)), _.each(items, function (item) {
                        item.setSelectable(!1), item.setLocked(!0)
                    }), this.project.view.draw()
                },
                _drawArrowedAxe: function (x1, y1, x2, y2) {
                    var items = [],
                        paths = [];
                    paths.push([x1, y1, x2, y2]);
                    var lineangle = Math.atan2(y2 - y1, x2 - x1),
                        ANGLE = .61,
                        TIPLENGTH = 7,
                        arrowHeight = Math.abs(TIPLENGTH / Math.cos(ANGLE)),
                        angleUp = lineangle + Math.PI + ANGLE,
                        angleDown = lineangle + Math.PI - ANGLE,
                        cosUp = Math.cos(angleUp) * arrowHeight,
                        sinUp = Math.sin(angleUp) * arrowHeight,
                        cosDown = Math.cos(angleDown) * arrowHeight,
                        sinDown = Math.sin(angleDown) * arrowHeight;
                    return paths.push([x2, y2, cosUp + x2, sinUp + y2]), paths.push([x2, y2, cosDown + x2, sinDown + y2]), paths.push([x1, y1, x1 - cosUp, y1 - sinUp]), paths.push([x1, y1, x1 - cosDown, y1 - sinDown]), _.each(paths, function (path) {
                        items.push(new paper.Path.Line({
                            from: [path[0], path[1]],
                            to: [path[2], path[3]],
                            strokeColor: "#000",
                            strokeWidth: 1
                        }))
                    }), items
                }
            }),
            PaperboardManager = PaperboardActionCollection.extend({
                model: PaperboardAction,
                initialize: function () {
                    var self = this;
                    project.options.handleSize = 8, this.redoQueue = new PaperboardActionCollection, this.items = Items, this.tools = toolCollection, this.tools.on("action.add", this.addAction.bind(this)), this.importing = !1, this.importPromise = new $.Deferred, this.importPromise.resolve(), this.backgroundHandler = new BackgroundHandler(project), this.on("background.drawgrid", function (style) {
                        self.backgroundHandler.drawTiledBackground(style)
                    }), this.on("background.drawaxes", function () {
                        self.backgroundHandler.drawAxesBackground()
                    }), this.setUser(null), project.activeLayer && this.setupLayer(project.activeLayer)
                },
                setUser: function (user) {
                    this.user = user, this.redoQueue.user = user
                },
                "export": function () {
                    return {
                        actions: this.toJSON(),
                        redo: this.redoQueue.toJSON(),
                        items: Items.toJSON()
                    }
                },
                "import": function (data) {
                    data = data || {}, _.isString(data) && (data = JSON.parse(data)), this.importing = !0, this.importPromise = new $.Deferred, project.clear(), this.addAction(this.addBoardPage()), this.reset(), this.redoQueue.reset(), Items.reset(), this.parse(data.actions), this.redoQueue.parse(data.redo), Items.parse(data.items), this.each(this._applyAction.bind(this)), this.draw(), this.trigger(_.sprintf("undo.%s", this.canUndo() ? "enabled" : "disabled")), this.trigger(_.sprintf("redo.%s", this.canRedo() ? "enabled" : "disabled")), this.trigger("layers.redraw"), this.importing = !1, this.importPromise.resolve()
                },
                addBoardPage: function (layer) {
                    var backgroundLayer = layer || new paper.Layer,
                        foregroundLayer = this.setupLayer(backgroundLayer);
                    return this.changeLayer(foregroundLayer), foregroundLayer
                },
                setupLayer: function (layer) {
                    var foregroundLayer = new paper.Layer;
                    return foregroundLayer.activate(), foregroundLayer._background = layer, layer._gridBackgroundStyle = "none", layer._hasAxesBackground = !1, foregroundLayer.clipped = !0, foregroundLayer.compositing = "destination-out", this.trigger("layer.added", foregroundLayer), this.importing || this.addAction(layer), foregroundLayer
                },
                changeLayer: function (layer) {
                    if (_.isNumeric(layer)) {
                        if (layer >= this.getLayerCount()) return null;
                        layer = project.layers[layer]
                    }
                    return _.each(project.layers, function (layer) {
                        layer.visible = !1
                    }), layer.activate(), layer.visible = !0, layer._background && (layer._background.visible = !0), layer
                },
                getLayerCount: function () {
                    return project.layers.length
                },
                draw: function () {
                    project.view.draw()
                },
                clear: function (type) {
                    var removed = [];
                    if (type ? _.each(project.activeLayer.children, function (item) {
                        item._itemType == type && removed.push(item)
                    }) : removed = project.activeLayer.removeChildren(), removed.length > 0) {
                        var items = {};
                        _.each(removed, function (item) {
                            var model = Items.get(item._itemID);
                            items[model.id] = model.addRevision(null)
                        });
                        var action = new PaperboardAction({
                            items: items,
                            owner: this.user,
                            type: PaperboardAction.ACTIONS.REMOVE
                        });
                        this.push(action), this._applyAction(action), this.triggerChange(action), this.clearRedo(), this.draw()
                    }
                },
                addFile: function (url, layer) {
                    layer = layer || project.activeLayer._index, layer instanceof paper.Layer && (layer = layer._index), this.importing || this._addSimpleAction("file", layer, url), this.trigger("file.added", url, layer)
                },
                addBackgroundUpdateAction: function (backgroundLayer) {
                    var layerIndex = backgroundLayer._index,
                        style = backgroundLayer._gridBackgroundStyle,
                        hasAxes = backgroundLayer._hasAxesBackground;
                    this._addSimpleAction("background", layerIndex, {
                        style: style,
                        hasAxes: hasAxes
                    })
                },
                _addSimpleAction: function (type, layerIndex, payload) {
                    var paperItem = new PaperboardItem({
                        type: type,
                        layer: layerIndex
                    });
                    paperItem.addRevision(payload, !1), Items.push(paperItem);
                    var items = {};
                    items[paperItem.id] = 0;
                    var action = new PaperboardAction({
                        items: items,
                        type: PaperboardAction.ACTIONS.ADD,
                        owner: this.user,
                        immutable: !0
                    });
                    this.push(action), this.triggerChange(action)
                },
                triggerChange: function (action, options) {
                    this.importing || this.trigger("changed", action, options)
                },
                addAction: function (item, previous) {
                    this.clearRedo();
                    var paperItem;
                    previous ? paperItem = Items.get(previous._itemID) : (paperItem = new PaperboardItem({
                        type: item._itemType,
                        layer: project.activeLayer._index
                    }), Items.push(paperItem));
                    var isLayer = item instanceof paper.Layer;
                    isLayer && paperItem.set("type", "layer"), paperItem.addRevision(item, !isLayer);
                    var action = paperItem.getLastAction();
                    action.set("owner", this.user), this.push(action), this.trigger("undo.enabled"), this.trigger("action.completed", item), this.triggerChange(action)
                },
                importActionFromJSON: function (json) {
                    var data = _.isObject(json) ? json : JSON.parse(json),
                        action = this.get(data.id),
                        undoAction = "undone" in data,
                        deleted = data.type == PaperboardAction.ACTIONS.DELETE;
                    if (undoAction) data.owner != this.user && (data.undone === !0 ? (this.remove(action), this._applyReverseAction(action), this.redoQueue.push(action)) : data.undone === !1 && (action = this.redoQueue.get(data.id), this.redoQueue.remove(action), this._applyAction(action), this.push(action)));
                    else if (deleted) data.owner != this.user && _.each(data.ids, function (actionID) {
                        this.redoQueue.get(actionID).delete()
                    }.bind(this));
                    else if (!action)
                        if (data.owner == this.user && data._old) {
                            if (action = this.get(data._old.id), action && (action.updateID(data.id), data._old.items)) {
                                var items = action.getItems(),
                                    newItems = {};
                                _.each(items, function (rev, itemID) {
                                    if (itemID in data._old.items) {
                                        var item = Items.get(itemID),
                                            newID = data._old.items[itemID];
                                        item.setID(newID), newItems[newID] = rev
                                    } else newItems[itemID] = rev
                                }), action.setItems(newItems)
                            }
                        } else data.owner != this.user && (this.importing = !0, action = new PaperboardAction, action.fromSingleJSON(data), this.push(action), this._applyAction(action), this.importing = !1);
                    this.draw()
                },
                undo: function () {
                    if (this.canUndo()) {
                        for (var action, i = this.models.length - 1; i >= 0; i--)
                            if (action = this.models[i], action.canUndo()) {
                                this.remove(action);
                                break
                            }
                        if (action.collection) return this.trigger("undo.disabled"), void 0;
                        this._applyReverseAction(action), this.draw(), this.redoQueue.push(action), this.triggerChange(action, {
                            undo: !0
                        }), this.trigger("redo.enabled"), this.canUndo() || this.trigger("undo.disabled")
                    }
                },
                redo: function () {
                    if (this.canRedo()) {
                        for (var action, i = this.redoQueue.models.length - 1; i >= 0; i--)
                            if (action = this.redoQueue.models[i], action.canUndo()) {
                                this.redoQueue.remove(action);
                                break
                            }
                        if (action.collection) return this.trigger("redo.disabled"), void 0;
                        this._applyAction(action), this.draw(), this.push(action), this.triggerChange(action, {
                            redo: !0
                        }), this.trigger("undo.enabled"), this.canRedo() || this.trigger("redo.disabled")
                    }
                },
                _applyAction: function (action) {
                    _.each(action.getRevisions(), function (item) {
                        if (item.model.isLayer()) action.setImmutable(!0), this.addBoardPage();
                        else if (item.model.isBackground()) {
                            action.setImmutable(!0);
                            var properties = item.model.getRevision(item.revision),
                                layer = item.model.getLayer();
                            this.trigger("change.background", layer._index, properties)
                        } else item.model.isFile() ? (action.setImmutable(!0), this.addFile(item.model.getRevision(item.revision), item.model.getLayer())) : item.model.showRevision(item.revision)
                    }.bind(this))
                },
                _applyReverseAction: function (action) {
                    _.each(action.getRevisions(), function (item) {
                        item.model.showPreviousRevision(item.revision)
                    })
                },
                clearRedo: function () {
                    for (var deleted = [], action = this.redoQueue.pop(); action;) action.delete(), deleted.push(action.id), action = this.redoQueue.pop();
                    deleted.length > 0 && (this.trigger("deleted", {
                        owner: this.user,
                        deleted: deleted,
                        type: PaperboardAction.ACTIONS.DELETE
                    }), this.canRedo() || this.trigger("redo.disabled"))
                },
                canUndo: function () {
                    return this.filter(function (model) {
                        return model.canUndo()
                    }).length > 0
                },
                canRedo: function () {
                    return this.redoQueue.filter(function (model) {
                        return model.canUndo()
                    }).length > 0
                }
            });
        return PaperboardManager
    };
    return function (paper, project) {
        var tools = paperTools(paper, project),
            manager = new(setup(paper, project, tools.createTools()));
        return manager
    }
}), define("referrals/page-share", function () {
    var shareOnTwitter = Backbone.View.extend({
        events: {
            "click .twitter-gift-share": "share"
        },
        share: function (event) {
            var $link = $(event.target),
                url = $("#referral-code").val(),
                text = $("#share-text").val(),
                params = ["text=" + encodeURIComponent(text)];
            _.str.include(text, url) || params.push("url=" + encodeURIComponent(url)), $link.attr("href", $link.attr("data-href") + "?" + params.join("&"))
        }
    });
    return {
        shareOnTwitter: shareOnTwitter
    }
}), define("referrals/reviews-hook", function () {
    function _validateEmail(email) {
        var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
        return re.test(email)
    }
    var ReviewsHookView = Backbone.Marionette.View.extend({
        ui: {
            mainSubmitButton: "#reviews-hook-main-submit",
            modalSubmitButton: "#reviews-hook-modal-submit",
            modalNoThanksButton: "#reviews-hook-modal-no",
            errorModal: "#reviews-hook-error-modal",
            successModal: "#reviews-hook-success-container",
            form: "#reviews-hook-form",
            formErrors: ".form-errors"
        },
        events: {
            "click #reviews-hook-main-submit": "validateAndSubmit",
            "click #reviews-hook-modal-no": "hideErrorModal",
            "click #reviews-hook-modal-submit": "submitForm"
        },
        initialize: function () {
            this.bindUIElements()
        },
        hideErrorModal: function () {
            this.ui.errorModal.modal("hide")
        },
        submitForm: function () {
            this.ui.form.submit()
        },
        formError: function (errHtml) {
            this.ui.formErrors.hide().html(errHtml).slideDown(150)
        },
        validateAndSubmit: function (event) {
            this.ui.formErrors.hide(), event.preventDefault();
            var $emailFields = this.ui.form.find("input[type=text]:visible"),
                emails = [],
                canSubmit = !0,
                errorModal = !1,
                self = this;
            return $emailFields.each(function () {
                var val = $(this).val();
                if (val) {
                    if (!_validateEmail(val)) return self.formError("Please make sure all emails are valid."), canSubmit = !1, void 0;
                    emails.push(val)
                } else errorModal = !0
            }), canSubmit ? 0 === emails.length ? (self.formError("Please enter at least one email."), !1) : _.uniq(emails).length != emails.length ? (self.formError("Please only use each email once."), !1) : (errorModal ? this.ui.errorModal.modal() : this.submitForm(), void 0) : !1
        }
    });
    return function (data) {
        return new ReviewsHookView(data)
    }
}), define("topic-explanations/views", function () {
    var TopicExplanationModalView = Backbone.View.extend({
        prompts: null,
        curIndex: 0,
        $headline: $("#topic-explanations-module > .module-content > h2"),
        $subheadline: $("#topic-explanations-module > .module-content > h3.subheadline"),
        $button: $("#topic-explanations-module > .module-content > div > a.btn"),
        events: {
            "click .next": "nextPrompt",
            "click .previous": "previousPrompt"
        },
        initialize: function (options) {
            this.prompts = options.prompts
        },
        _switchPrompt: function (newPrompt) {
            this.$headline.text(newPrompt.prompt), this.$subheadline.text(newPrompt.subheadline), this.$button.attr("href", newPrompt.addExplanationURL)
        },
        nextPrompt: function () {
            return this.curIndex += 1, this.curIndex == this.prompts.length && (this.curIndex = 0), this._switchPrompt(this.prompts[this.curIndex]), !1
        },
        previousPrompt: function () {
            return this.curIndex -= 1, -1 == this.curIndex && (this.curIndex = this.prompts.length - 1), this._switchPrompt(this.prompts[this.curIndex]), !1
        }
    });
    return {
        TopicExplanationModalView: TopicExplanationModalView
    }
}), define("session/managers", function () {
    var ChatManager = function () {
        var chat = $("#ta-widget"),
            currentHeight = 546;
        this.updateHeight = function (toRemove) {
            var newHeight = currentHeight - toRemove;
            currentHeight != newHeight && (chat.css({
                height: newHeight
            }), currentHeight = newHeight)
        }
    };
    return {
        chatManager: new ChatManager
    }
}), define("session/socket", ["socket", "config"], function (socket, config) {
    var LessonSocket = function (lessonCode) {
        this.room = _.sprintf("lesson=%s", lessonCode), this.socket = socket.connect("lesson");
        var self = this;
        this.socket.done(function () {
            self.socket.socket.on("reconnect", function () {
                self.webrtc(config.opentok.webrtc)
            })
        }), this.socket.enableRollbarLogging()
    };
    _.extend(LessonSocket.prototype, {
        subscribe: function (events) {
            this.socket.subscribe(this.room, events)
        },
        emit: function (event, data) {
            this.socket.emit(event, data)
        },
        emitToRoom: function (event, data) {
            this.socket.emitToRoom(this.room, event, data)
        },
        emitToOthers: function (event, data) {
            this.socket.emitToOthers(this.room, event, data)
        },
        webrtc: function (enabled) {
            this.emit("webrtc", enabled)
        }
    });
    var sockets = {};
    return function (lessonCode) {
        return lessonCode in sockets || (sockets[lessonCode] = new LessonSocket(lessonCode)), sockets[lessonCode]
    }
}), define("session/paperboard", ["session/constants", "paperboard/views", "util", "session/socket", "config"], function (constants, paperboard, util, socket, config) {
    var lessonSocket = socket(config.lessonCode);
    return function ($el, options, lessonCode) {
        var $canvas = $el.find("canvas"),
            components = paperboard.getPaperboardComponents($canvas.prop("id")),
            pbBase = components.Paperboard,
            SharedPaperboard = pbBase.extend({
                events: {
                    "click .share-file": "toggleUploadDrawer",
                    "click .upload-drawer-close": "closeUploadDrawer"
                },
                modelEvents: {
                    "file.added": "fileAdded",
                    changed: "syncAction",
                    deleted: "syncDelete"
                },
                ui: {
                    uploadDrawer: ".upload-drawer",
                    uploadForm: ".upload-doc",
                    uploadError: ".upload-error",
                    uploadFile: ".upload-file",
                    uploadFields: ".upload-fields",
                    uploadProgress: ".upload-progress",
                    uploadProgressBar: ".upload-progress .bar"
                },
                initialize: function () {
                    pbBase.prototype.initialize.apply(this, arguments), this.model.setUser(config.userCode), this.syncURL = _.sprintf("s/%s/sketchpad/", lessonCode), this.updating = !1, this.fileUploading = !1, this.pdfJSLoaded = new $.Deferred, this.syncing = !1, this.syncQueue = [], this.userThumbs = {}, this.showWhenPageAdded = {}, this.setupFileUpload()
                },
                syncAction: function (action, options) {
                    options = options || {};
                    var undone = null;
                    options.redo ? undone = !1 : options.undo && (undone = !0), this._sync({
                        action: action,
                        undone: undone
                    })
                },
                syncDelete: function (data) {
                    data.deleted = _.filter(data.deleted, function (id) {
                        return _.isNumeric(id) ? id : !1
                    }), data.deleted.length > 0 && this._sync(data)
                },
                _sync: function (data, options) {
                    if (options = options || {}, this.syncing && !options.process) return this.syncQueue.push(data), void 0;
                    var self = this,
                        action = data.action ? JSON.stringify(data.action.toSingleJSON(data.undone)) : data;
                    this.syncing = !0, util.API.post(this.syncURL, {
                        checkDataForDoubleSubmit: !0,
                        data: {
                            action: action
                        },
                        error: function () {
                            var retries = options.retries || 0;
                            3 > retries && self.syncQueue.unshift(data, {
                                process: !0,
                                retries: ++options.retries
                            })
                        },
                        complete: function () {
                            var next = self.syncQueue.shift();
                            next ? self._sync(next, {
                                process: !0
                            }) : self.syncing = !1
                        }
                    })
                },
                updateAction: function (data) {
                    this.model.importActionFromJSON(data.action)
                },
                load: function () {
                    this.socketSubscribe(), util.API.get(this.syncURL, {
                        success: function (data) {
                            data.isRaphael ? this.setupRaphael(data) : this.model.import(data.sketchpadData)
                        }.bind(this)
                    }), window.amplify.publish("component.paperboard.loaded")
                },
                socketSubscribe: function () {
                    var events = {
                        "changed:page": this.otherPageChanged.bind(this)
                    };
                    events[lessonSocket.room + ".sketchpad"] = this.updateAction.bind(this), lessonSocket.subscribe(events), this.on("changed:layer", this.pageChanged.bind(this))
                },
                otherPageChanged: function (data) {
                    if (!this.userThumbs[data.userCode]) {
                        if (!config.userPhotos[data.userCode]) return;
                        this.userThumbs[data.userCode] = config.userPhotos[data.userCode].clone()
                    }
                    var $page = this.pagination.getPage(data.pageNum);
                    $page.exists() ? ($page.find("a").append(this.userThumbs[data.userCode]), this.userThumbs[data.userCode].tooltip()) : this.showWhenPageAdded = data
                },
                pageChanged: function (pageNum) {
                    this.model.importing && this.showWhenPageAdded.pageNum === pageNum && this.otherPageChanged({
                        userCode: this.showWhenPageAdded.userCode,
                        pageNum: pageNum
                    }), this.emitPageChange(pageNum)
                },
                emitPageChange: function (pageNum) {
                    lessonSocket.emitToOthers("changed:page", {
                        userCode: config.uuid,
                        pageNum: pageNum || this.getPageNumber()
                    })
                },
                toggleUploadDrawer: function (event) {
                    event && event.preventDefault(), this.ui.uploadDrawer.toggle()
                },
                closeUploadDrawer: function (event) {
                    event && event.preventDefault(), this.ui.uploadDrawer.hide()
                },
                fileAdded: function (url, layerNumber, onImageLoad) {
                    this.model.importPromise.done(function () {
                        var layer = components.project.layers[layerNumber],
                            ext = _.strRightBack(url, ".").toLowerCase();
                        if ("pdf" == ext) {
                            var self = this;
                            this.loadPDFJS().done(function () {
                                self.loadPDF(url, layer, layerNumber).done(function () {
                                    _.isFunction(onImageLoad) ? onImageLoad() : self.finishUpload()
                                })
                            })
                        } else {
                            var img = new Image;
                            img.onload = function () {
                                _.isFunction(onImageLoad) ? onImageLoad() : (this.finishUpload(), layerNumber === components.project.activeLayer._index && (this.resizeCanvas(img.width, img.height), this.options.toggleGridControl(!1)))
                            }.bind(this), img.src = url;
                            var $li = $("<li/>").append(img);
                            layer.$imageList.append($li)
                        }
                    }.bind(this))
                },
                finishUpload: function () {
                    this.ui.uploadFields.show(), this.ui.uploadProgress.hide(), this.closeUploadDrawer()
                },
                loadPDF: function (url, layer, layerNumber) {
                    var self = this,
                        d = new $.Deferred;
                    return window.PDFJS.getDocument(url).then(function (pdf) {
                        var $imageList = layer.$imageList,
                            canvasModified = !1,
                            rendered = 0;
                        d.progress(function () {
                            ++rendered == pdf.numPages && d.resolve()
                        });
                        for (var onPageLoad = function (page) {
                            var viewport = page.getViewport(1),
                                $pdfCanvas = $("<canvas>");
                            if ($("<li/>").append($pdfCanvas).appendTo($imageList), $pdfCanvas.prop("height", viewport.height).prop("width", viewport.width), !canvasModified) {
                                var realHeight = viewport.height * pdf.numPages;
                                layerNumber === components.project.activeLayer._index && (self.resizeCanvas(viewport.width, realHeight), canvasModified = !0)
                            }
                            page.render({
                                canvasContext: $pdfCanvas[0].getContext("2d"),
                                viewport: viewport
                            }), d.notify()
                        }, i = 1; i <= pdf.numPages; i++) pdf.getPage(i).then(onPageLoad)
                    }), d
                },
                setupFileUpload: function () {
                    var self = this;
                    util.fileUpload(this.ui.uploadForm, {
                        hideErrorModals: !0,
                        beforeAdd: function () {
                            self.fileUploading = !0, self.ui.uploadProgressBar.text("Uploading...")
                        },
                        done: function (e, data) {
                            self.ui.uploadProgressBar.text("Upload complete! Rendering..."), self.hasContent() && self.newBoardPage(), self.model.addFile(data.result.url), self.ui.uploadFile.val("")
                        },
                        afterFail: function () {
                            self.ui.uploadError.fadeIn("fast"), self.ui.uploadFields.show(), self.ui.uploadProgress.hide()
                        },
                        always: function () {
                            self.fileUploading = !1
                        },
                        afterProgress: function () {
                            self.ui.uploadFields.hide()
                        }
                    })
                }
            });
        return components.Paperboard = SharedPaperboard, paperboard.init($el, options, components)
    }
}), define("session/models", ["schedule/models", "session/socket", "util", "config", "rollbar"], function (schedule, socket, util, config, rollbar) {
    var ENDPOINTS = {
            "view-confirmed-lesson": "s/%s/view-confirmed-lesson/",
            "get-conference-info": "s/%s/get-conference-info/"
        },
        LessonConference = Backbone.Model.extend({
            defaults: {
                receiver: !1
            },
            initialize: function () {
                this.socket = socket(config.lessonCode), this.socket.subscribe({
                    new_conference: this.loadConference.bind(this)
                })
            },
            loadConference: function (data) {
                return data.initiator == config.lessonUser ? !1 : (this.setConferenceInfo(!1, !0), void 0)
            },
            emitCreateCall: function () {
                this.socket.emitToRoom("new_conference", {
                    initiator: config.userCode
                })
            },
            setConferenceInfo: function (silent, receiver) {
                return silent = !!silent || !1, receiver = !!receiver || !1, util.API.get(_.sprintf(ENDPOINTS["get-conference-info"], config.lessonCode), {
                    success: function (data) {
                        this.set({
                            code: data.conferenceCode,
                            phone: data.conferenceNumber,
                            receiver: receiver
                        }, {
                            silent: silent
                        })
                    }.bind(this)
                })
            }
        }),
        SessionProposal = schedule.Proposal.extend({
            lessonCode: null,
            initialize: function (options) {
                this.lessonCode = options.lessonCode
            },
            getOptions: function (options, csrf) {
                return options = schedule.Proposal.prototype.getOptions.call(this, options, csrf), options.data = options.data || {}, _.isString(options.data) ? options.data += "&lessonCode=" + this.lessonCode : _.isObject(options.data) && (options.data.lessonCode = this.lessonCode), options
            },
            viewConfirmedLesson: function (options) {
                util.API.get(_.sprintf(ENDPOINTS["view-confirmed-lesson"], this.lessonCode), this.getOptions(options))
            }
        }),
        Session = Backbone.Model.extend({
            pollStartTime: null,
            pollEndTime: null,
            pollLocked: !1,
            defaultRetryData: {},
            getSessionStatus: function (retryData) {
                retryData || (retryData = this.defaultRetryData);
                var retryFn = function () {
                    this.getSessionStatus(retryData)
                }.bind(this);
                if (this.pollLocked) return setTimeout(retryFn, 20), void 0;
                this.pollLocked = !0, this.pollStartTime = new Date;
                var ts = this.pollStartTime.getTime().toString();
                util.API.post(config.LESSON_STATUS_URL + "?_=" + ts, {
                    csrf: !0,
                    success: function (data) {
                        this.checkPollTime(), this.pollLocked = retryData.success(data), setTimeout(retryFn, window.POLL_INTERVAL_MS)
                    }.bind(this),
                    error: function () {
                        rollbar.log("getSessionStatus failed"), this.pollLocked = !1, window.retry(retryData)
                    }.bind(this)
                })
            },
            createLessonEvent: function (retryData) {
                if (this.pollLocked) return setTimeout(function () {
                    this.createLessonEvent(retryData)
                }.bind(this), 20), void 0;
                this.pollLocked = !0, this.pollStartTime = new Date;
                var ts = this.pollStartTime.getTime().toString();
                util.API.post(config.CREATE_LESSON_EVENT_URL + "?_=" + ts, {
                    csrf: !0,
                    data: {
                        event: retryData.event
                    },
                    success: function (data) {
                        this.checkPollTime(), this.pollLocked = retryData.success(data)
                    }.bind(this),
                    error: function () {
                        rollbar.log("createLessonEvent failed: " + retryData.event), this.pollLocked = !1, window.retry(retryData)
                    }.bind(this)
                })
            },
            checkPollTime: function () {
                this.pollEndTime = new Date;
                var pollRoundtripTimeMs = this.pollEndTime - this.pollStartTime;
                pollRoundtripTimeMs >= 1e3 && rollbar.log("SLOW POLLING ROUNDTRIP (" + pollRoundtripTimeMs + " ms)")
            },
            submitQuestion: function (options) {
                util.API.post(config.SUBMIT_QUESTION_URL, options)
            }
        });
    return {
        LessonConference: LessonConference,
        Session: Session,
        SessionProposal: SessionProposal
    }
}), define("session/constants", ["base/constants"], function (base) {
    var LESSON_STEP = {
            OFFLINE: 0,
            FINDING_A_TUTOR: 1,
            READY_TO_WORK: 2,
            WAITING_FOR_APPROVAL: 3,
            ABANDONED: 4,
            TIMEOUT: 5,
            CANCELED: 6,
            ENABLE_AUDIO_OR_VIDEO: 7,
            VIEW_QUESTION: 8,
            ALREADY_TAKEN: 9,
            WAITING_FOR_OTHER_PARTY_EARLY: 101,
            WAITING_FOR_OTHER_PARTY: 102,
            OTHER_PARTY_LATE: 103,
            OTHER_PARTY_HAS_ARRIVED: 105,
            OTHER_PARTY_ALREADY_HERE: 106,
            LATE_BUT_FIRST: 107,
            MISSED_LESSON: 108,
            SCHEDULE_NEW_LESSON: 201,
            LOADING: 801,
            LOAD_RETRY: 802,
            STUDENT_LOAD_FAIL: 803,
            TUTOR_LOAD_FAIL: 804,
            LESSON: 901,
            PAUSED: 902,
            SUSPENDED: 903,
            ENDED: 904,
            VOIDED: 905,
            SCHEDULE_ATTEMPT: 950,
            SCHEDULE_CANCEL: 951,
            SCHEDULE_SUCCESS: 952
        },
        LESSON_STEP_STR = {};
    for (var key in LESSON_STEP) LESSON_STEP_STR[LESSON_STEP[key]] = key;
    var TERMINAL_STEPS = [LESSON_STEP.OFFLINE, LESSON_STEP.ABANDONED, LESSON_STEP.TIMEOUT, LESSON_STEP.CANCELED, LESSON_STEP.ALREADY_TAKEN, LESSON_STEP.VOIDED, LESSON_STEP.SCHEDULE_SUCCESS],
        SCHEDULING_STEPS = [LESSON_STEP.SCHEDULE_ATTEMPT, LESSON_STEP.SCHEDULE_CANCEL, LESSON_STEP.SCHEDULE_SUCCESS],
        LOADING_FINISHED_STEPS = [LESSON_STEP.WAITING_FOR_APPROVAL, LESSON_STEP.WAITING_FOR_OTHER_PARTY_EARLY, LESSON_STEP.WAITING_FOR_OTHER_PARTY, LESSON_STEP.LATE_BUT_FIRST, LESSON_STEP.OTHER_PARTY_LATE, LESSON_STEP.OTHER_PARTY_HAS_ARRIVED, LESSON_STEP.OTHER_PARTY_ALREADY_HERE, LESSON_STEP.LESSON, LESSON_STEP.PAUSED, LESSON_STEP.SUSPENDED],
        WORKSPACE_COVER_STEPS = [LESSON_STEP.CANCELED, LESSON_STEP.STUDENT_LOAD_FAIL, LESSON_STEP.TUTOR_LOAD_FAIL],
        LESSON_EVENT = {
            SUSPEND: 1,
            RECOVER: 2,
            PAUSE: 3,
            RESUME: 4,
            ABANDON: 5,
            LOAD_FAIL: 6,
            VOID: 7,
            ARRIVE: 8,
            STREAM: 9,
            APPROVE: 10,
            TIMEOUT: 11,
            LOAD: 12,
            READY: 13,
            DEPART: 14,
            CANCEL: 15,
            FLAG: 16,
            END: 17,
            LOAD_RETRY: 18,
            AUDIO_OR_VIDEO_ACTIVE: 19,
            AUDIO_OR_VIDEO_FAIL: 20,
            SCHEDULE_ATTEMPT: 21,
            SCHEDULE_CANCEL: 22,
            SCHEDULE_SUCCESS: 23,
            ACCEPT_QUESTION: 24,
            REJECT_QUESTION: 25,
            SCREEN_START: 29,
            SCREEN_END: 30,
            SCREEN_PAUSE: 31,
            SCREEN_RESUME: 32
        },
        LESSON_MEDIUM = {
            VIDEO: 1,
            AUDIO: 2,
            TEXT: 3
        };
    return {
        LESSON_STEP: LESSON_STEP,
        LESSON_STEP_STR: LESSON_STEP_STR,
        TERMINAL_STEPS: TERMINAL_STEPS,
        SCHEDULING_STEPS: SCHEDULING_STEPS,
        LOADING_FINISHED_STEPS: LOADING_FINISHED_STEPS,
        WORKSPACE_COVER_STEPS: WORKSPACE_COVER_STEPS,
        LESSON_EVENT: LESSON_EVENT,
        LESSON_MEDIUM: LESSON_MEDIUM,
        ROLE: base.ROLE,
        ROLE_STR: base.ROLE_STR
    }
}), define("session/cursor", ["session/socket", "config"], function (socket, config) {
    var lessonSocket = socket(config.lessonCode),
        LessonCursor = function ($cursor) {
            this.speed = 200, this.$canvas = null, this.$cursor = $cursor, this.$container = this.$cursor.parents(".container"), this.className = null, this.position = null, this.tab = "whiteboard", this.layer = 0, this.other = {
                className: null,
                visible: !1,
                tab: "whiteboard",
                layer: 0
            }
        };
    return _(LessonCursor.prototype).extend({
        setup: function (paperboard) {
            this.$canvas = paperboard.ui.canvas, paperboard.on("tool:activated", this.toolChanged.bind(this)), paperboard.on("changed:layer", this.layerChanged.bind(this)), this.toolChanged(paperboard.activeToolView), lessonSocket.subscribe({
                "paperboard:mousemove": this.updateOtherPosition.bind(this)
            });
            var updatePosition = _.throttle(this.updatePosition.bind(this), this.speed);
            $("html").on("mousemove", updatePosition)
        },
        hide: function () {
            return this.other.visible && (this.other.visible = !1, this.$cursor.fadeOut("fast")), this
        },
        show: function () {
            return this.other.visible || (this.other.visible = !0, this.$cursor.fadeIn("fast")), this
        },
        emit: function () {
            lessonSocket.emitToOthers("paperboard:mousemove", {
                position: this.position,
                className: this.className,
                layer: this.layer,
                tab: this.tab
            })
        },
        updatePosition: function (event) {
            if (event.target === this.$canvas[0]) {
                var containerOffset = this.$container.offset();
                this.position = {
                    x: event.clientX + document.body.scrollLeft - containerOffset.left,
                    y: event.clientY + document.body.scrollTop - containerOffset.top
                }, this.emit()
            } else this.position && (this.position = null, this.emit())
        },
        setClassName: function (className) {
            this.className = className, this.emit()
        },
        updateOtherPosition: function (data) {
            if (this.other.layer = data.layer, this.other.tab = data.tab, !data.position || this.tab !== this.other.tab || "whiteboard" !== this.tab || this.layer != data.layer) return this.hide(), void 0;
            this.other.className !== data.className && (this.$cursor.removeClass(), data.className && this.$cursor.addClass(data.className), this.other.className = data.className);
            var containerOffset = this.$container.offset(),
                cursorWidth = this.$cursor.width() / 2,
                left = data.position.x - cursorWidth + containerOffset.left,
                top = data.position.y - cursorWidth + containerOffset.top;
            this.other.visible ? this.$cursor.animate({
                left: left,
                top: top
            }, this.speed, "linear") : (this.$cursor.css({
                left: left,
                top: top
            }), this.show())
        },
        toolChanged: function (view) {
            this.setClassName(view.getCursorClass())
        },
        layerChanged: function (pageNum) {
            this.other.layer == pageNum && this.other.tab === this.tab ? this.show() : this.hide(), this.layer = pageNum
        },
        tabChanged: function (tab) {
            this.other.tab == tab && this.other.layer === this.layer ? this.show() : this.hide(), this.tab = tab
        }
    }), LessonCursor
}), define("session/steps", ["schedule/views", "session/models", "session/constants", "session/video/views", "session/audiobridge/views", "chat/view-utils", "util", "config", "rollbar"], function (scheduleViews, models, constants, video, lessonConferenceRegion, chatUtils, util, config, rollbar) {
    var timer, progress, scheduleModal, studentLessonTimer, readySoundPlayed = !1,
        startProgressBar = function (params) {
            for (var bar = params.bar, progressText = params.copy, progressBarText = function (newText, waitTime) {
                setTimeout(function () {
                    progressText.innerHTML = newText
                }, waitTime)
            }, lastPercent = 0, lastTime = 0, s = 0; s < params.steps.length; s++) {
                var step = params.steps[s];
                if (step.increment = (step.percent - lastPercent) * params.msPerIncrement / step.time, lastTime > params.elapsedMs) {
                    var timeToThisStep = lastTime - params.elapsedMs;
                    progressBarText(step.copy, timeToThisStep)
                }
                if (params.elapsedMs < step.time && params.elapsedMs >= lastTime) {
                    var timeFromStart = params.elapsedMs - lastTime;
                    progressText.innerHTML = step.copy;
                    var startingWidth = lastPercent + step.increment * timeFromStart / params.msPerIncrement;
                    bar.style.width = startingWidth + "%"
                }
                lastPercent = step.percent, lastTime = step.time
            }
            return window.setInterval(function () {
                for (var width = parseFloat(bar.style.width), s = 0; s < params.steps.length; s++) {
                    var step = params.steps[s];
                    if (width < step.percent) {
                        width += step.increment, bar.style.width = width + "%";
                        break
                    }
                }
            }, params.msPerIncrement)
        },
        startTimer = function (timerElem, timeLeftMs) {
            timeLeftMs += window.POLL_INTERVAL_MS / 2;
            var timeStarted = new Date,
                pad = function (num) {
                    return num > 9 ? num : "0" + num
                },
                formatTime = function (time) {
                    if (0 >= time) return "0:00";
                    var days = Math.floor(time / 86400);
                    time -= 86400 * days;
                    var hours = Math.floor(time / 3600);
                    time -= 3600 * hours;
                    var minutes = Math.floor(time / 60),
                        seconds = time - 60 * minutes;
                    return days ? days + ":" + pad(hours) + ":" + pad(minutes) + ":" + pad(seconds) : hours ? hours + ":" + pad(minutes) + ":" + pad(seconds) : minutes + ":" + pad(seconds)
                };
            timer = setInterval(function () {
                var now = new Date,
                    timeDelta = Math.round((timeStarted - now + timeLeftMs) / 1e3);
                timerElem.html(formatTime(timeDelta))
            }, 1e3)
        },
        playReadySound = function () {
            if (!readySoundPlayed) try {
                var sound = document.getElementById("ready-sound");
                sound.volume = .3, sound.play()
            } catch (err) {}
        },
        SessionScheduleView = scheduleViews.ProposalModalView.extend({
            sup: scheduleViews.ProposalModalView.prototype,
            lessonCode: null,
            isTutor: !1,
            $step: $(),
            $steps: {},
            createEventCallback: function () {},
            initialize: function (options) {
                this.sup.initialize.call(this, options), this.lessonCode = options.lessonCode, this.isTutor = options.isTutor, this.createEventCallback = options.createEventCallback;
                var steps = ["schedule", "create", "confirm", "counter", "counter-confirm", "accepted"];
                _.each(steps, function (el) {
                    this.$steps[el] = this.$(".scheduling-step-" + el)
                }.bind(this)), this.$step = this.$steps.schedule, _.extend(this.events, {
                    "click .attempt-schedule": "startScheduling",
                    "click .no-thanks": "stopScheduling",
                    "click #stop-proposal": "stopProposal",
                    "click #accept-original": "confirmProposal"
                }), this.setModel(new models.SessionProposal({
                    lessonCode: options.lessonCode
                }))
            },
            showStep: function (name) {
                this.$steps[name].show(), this.$step = this.$steps[name]
            },
            hideStep: function (name) {
                name ? this.$steps[name].hide() : this.$step.hide()
            },
            removeStep: function (name) {
                name ? this.$steps[name].remove() : this.$step.remove()
            },
            showModal: function (data) {
                data && this.$step.html(data), this.$el.show()
            },
            stopScheduling: function () {
                window.delayedReload()
            },
            stopProposal: function () {
                this.createEventCallback(constants.LESSON_EVENT.SCHEDULE_CANCEL), window.delayedReload()
            },
            startScheduling: function () {
                return this.createEventCallback(constants.LESSON_EVENT.SCHEDULE_ATTEMPT), !1
            },
            showAddLessonSuccess: function (data) {
                this.removeStep("schedule"), this.showStep("create"), this.sup.showAddLessonSuccess.call(this, data)
            },
            createSuccess: function (data) {
                data && data.newForm ? this.sup.createSuccess.call(this, data) : (this.removeStep("create"), this.showStep("confirm"))
            },
            confirmSuccess: function (data) {
                this.newLessonModel || (data.fromStatusCheck || this.createEventCallback(constants.LESSON_EVENT.SCHEDULE_SUCCESS), this.newLessonModel = new models.SessionProposal({
                    lessonCode: data.lessonCode
                }), this.newLessonModel.viewConfirmedLesson({
                    success: function (data) {
                        this.removeStep(), this.showStep("accepted"), this.showModal(data.content)
                    }.bind(this)
                }))
            },
            showCounterStep: function () {
                this.removeStep("confirm"), this.hideStep(), this.showStep("counter")
            },
            showCounterSuccess: function (data) {
                this.showCounterStep(), this.sup.showCounterSuccess.call(this, data)
            },
            submitCounterSuccess: function (data) {
                data.form ? this.sup.submitCounterSuccess.call(this, data) : (this.hideStep(), this.showStep("counter-confirm"))
            },
            checkProposal: function (proposal) {
                this.model.id != proposal.id && (this.model.id = proposal.id, proposal.isProposer || "NEW" != proposal.status || (proposal.previous ? this.showCounterStep() : this.createSuccess(), this.showProposal(this.model.viewRespond.bind(this.model))), "CONFIRMED" == proposal.status && this.confirmSuccess({
                    lessonCode: proposal.lessonCode,
                    fromStatusCheck: !0
                }))
            }
        }),
        Step = util.BaseView.extend({
            setDefaults: function () {
                this.elements = []
            },
            forwards: function () {},
            backwards: function () {},
            transition: function (previousStep, workspace) {
                for (var hide = (previousStep.elements || []).slice(0), show = this.elements.slice(0), i = 0; i < hide.length; i++) {
                    var loc = $.inArray(hide[i], show); - 1 != loc && (show.splice(loc, 1), hide.splice(i, 1), i--)
                }
                var id = this.id;
                workspace.adjustVideoPosition(id), $(hide.join(", ")).hide(200), setTimeout(function () {
                    $(show.join(", ")).show(200), setTimeout(function () {
                        if (workspace.isWorkspaceCoverStep(id)) {
                            var offsetTop = $("#tab-and-status-container").offset().top + $("#top-nav").height(),
                                h = $(document).height() - offsetTop - 1;
                            $("#cover").css({
                                top: offsetTop + "px",
                                height: h + "px"
                            }).show()
                        } else $("#cover").hide();
                        workspace.adjustVideoPosition(id)
                    }, 300)
                }, 200)
            }
        }),
        DelayedReload = Step.extend({
            forwards: window.delayedReload,
            transition: function () {}
        }),
        FindingATutor = Step.extend({
            setDefaults: function () {
                this.elements = ["#finding-a-tutor-container", "#finding-a-tutor-progress-bar", "#expert-facepile", "#finding-a-tutor-subheadline"]
            },
            forwards: function (data) {
                progress = startProgressBar({
                    bar: document.getElementById("finding-a-tutor-bar-progress"),
                    copy: document.getElementById("finding-a-tutor-bar-text"),
                    elapsedMs: 1e3 * data.progressBarSeconds,
                    msPerIncrement: 500,
                    steps: [{
                        percent: 10,
                        time: 5e3,
                        copy: "1. Identifying best matches"
                    }, {
                        percent: 35,
                        time: 15e3,
                        copy: "2. Notifying experts"
                    }, {
                        percent: 50,
                        time: 1e4,
                        copy: "2. Notifying experts"
                    }, {
                        percent: 70,
                        time: 3e4,
                        copy: "3. Waiting for responses"
                    }, {
                        percent: 100,
                        time: 9e4,
                        copy: "3. Waiting for responses"
                    }]
                })
            },
            backwards: function () {
                window.clearInterval(progress)
            }
        }),
        ReadyToWork = Step.extend({
            setDefaults: function () {
                this.elements = ["#finding-a-tutor-container", "#expert-ready-to-work"]
            },
            forwards: function (data, workspace) {
                $("#expert-info-container").html(_.template($("#tutor-info-template").html(), data)), $(".tutor-name").html(data.tutorName), "" !== data.tutorExperience && ($(".tutor-experience").html(data.tutorExperience), $(".tutor-experience-container").show()), data.tutorThumbSmall && document.getElementById("tutor-thumb-small").setAttribute("src", data.tutorThumbSmall), window.ETHERPAD_URL = data.etherpadURL, config.userPhotos[data.tutorID] = config.getViewingIcon(data.tutorName), config.userPhotos[data.studentID] = config.getViewingIcon("A student"), workspace.viewLesson || (window.amplify.publish("check-tech-status"), workspace.tokbox.collection.load(), workspace.emitState()), Backbone.trigger("lesson.ready", {
                    student: data.studentID,
                    tutor: data.tutorID
                }), config.otherUser = config.lessonRole == constants.ROLE.STUDENT ? data.tutorID : data.studentID, $("#session-question-form").removeClass("span6").addClass("span4"), $("#finding-a-tutor > div > div > h1.headline").html("<span id='tutor-name-headline'>" + data.tutorName + "</span> is <span class='ready'>ready</span> to work with you!</h1>"), playReadySound()
            }
        }),
        WaitingForApproval = Step.extend({
            setDefaults: function () {
                this.elements = ["#session-workspace-container", "#waiting-for-approval-container"]
            },
            forwards: function (data, workspace) {
                workspace.tokbox.collection.sendWebRTCStatus(), progress = startProgressBar({
                    bar: document.getElementById("waiting-for-approval-bar-progress"),
                    copy: document.getElementById("waiting-for-approval-bar-text"),
                    elapsedMs: 1e3 * data.progressBarSeconds,
                    msPerIncrement: 100,
                    steps: [{
                        percent: 20,
                        time: 5e3,
                        copy: "1. Processing acceptance"
                    }, {
                        percent: 35,
                        time: 1e4,
                        copy: "2. Sending student your profile"
                    }, {
                        percent: 50,
                        time: 15e3,
                        copy: "3. Awaiting student approval"
                    }, {
                        percent: 75,
                        time: 45e3,
                        copy: "3. Awaiting student approval"
                    }, {
                        percent: 90,
                        time: 9e4,
                        copy: "3. Awaiting student approval"
                    }, {
                        percent: 100,
                        time: 9e5,
                        copy: "3. Awaiting student approval"
                    }]
                })
            },
            backwards: function () {
                window.clearInterval(progress)
            }
        }),
        Abandoned = Step.extend({
            forwards: function (data) {
                return config.lessonRole == constants.ROLE.STUDENT ? (window.createLesson({
                    lastLessonCode: config.lessonCode,
                    isForwardedFrom: !0
                }), void 0) : "undefined" == typeof data.profileURL ? (window.delayedReload(), void 0) : (this.elements = ["#abandonment-explanation-container"], $("#abandonment-tutor-info").html(_.template($("#tutor-info-template").html(), data)), "" !== data.tutorExperience && ($(".tutor-experience").html(data.tutorExperience), $(".tutor-experience-container").show()), $("#abandoned-profile-link").attr("href", data.profileURL), void 0)
            }
        }),
        Timeout = Step.extend({
            setDefaults: function () {
                this.elements = ["#finding-a-tutor-container", "#finding-a-tutor-progress-bar", "#expert-facepile", "#finding-a-tutor-subheadline"]
            },
            forwards: function () {
                config.lessonRole == constants.ROLE.TUTOR ? window.location.reload() : $("#message-modal").modal({
                    backdrop: "static",
                    keyboard: !1
                })
            }
        }),
        Canceled = Step.extend({
            forwards: function (data, workspace) {
                return config.lessonRole == constants.ROLE.TUTOR ? ($("#popup-content").html($("#error-canceled-request").html()), window.hideLightboxClose(), window.showLightbox(), void 0) : workspace.atFault == constants.ROLE.STUDENT ? (this.elements = ["#session-workspace-container", "#load-fail-container", "#fix-load-fail"], void 0) : (window.createLesson({
                    lastLessonCode: config.lessonCode,
                    isForwardedFrom: !1
                }), void 0)
            }
        }),
        ViewQuestion = Step.extend({
            setDefaults: function () {
                this.elements = ["#view-question-container"]
            }
        }),
        AlreadyTaken = DelayedReload,
        Waiting = Step.extend({
            setDefaults: function () {
                this.elements = ["#session-workspace-container", "#prescheduled-presession-container"], this.waitingEl = this.getWaitingEl()
            },
            getWaitingEl: function () {
                return ""
            },
            postInit: function () {
                this.elements.push(this.waitingEl)
            },
            forwards: function (data) {
                startTimer($(this.waitingEl + " .timer"), data.timerMS)
            },
            backwards: function () {
                window.clearInterval(timer)
            }
        }),
        WaitingForOtherPartyEarly = Waiting.extend({
            getWaitingEl: function () {
                return "#prescheduled-waiting-for-other-party-early"
            }
        }),
        WaitingForOtherParty = Waiting.extend({
            getWaitingEl: function () {
                return "#prescheduled-waiting-for-other-party"
            }
        }),
        WaitingForOtherPartyLate = Waiting.extend({
            getWaitingEl: function () {
                return "#prescheduled-other-party-late"
            }
        }),
        OtherPartyHasArrived = Waiting.extend({
            getWaitingEl: function () {
                return "#prescheduled-other-party-has-arrived"
            },
            forwards: function () {
                playReadySound(), $("#prescheduled-other-party-has-arrived-modal").modal("show")
            }
        }),
        OtherPartyAlreadyHere = Waiting.extend({
            getWaitingEl: function () {
                return "#prescheduled-other-party-already-here"
            }
        }),
        Late = Waiting.extend({
            getWaitingEl: function () {
                return "#prescheduled-late"
            },
            forwards: function () {}
        }),
        MissedLesson = DelayedReload,
        Loading = Step.extend({
            setDefaults: function () {
                this.elements = ["#session-loading-container"]
            },
            forwards: function (data, workspace) {
                if (workspace.loadFinished) return rollbar.log("Hit step = LOADING when loading is finished, refreshing the page."), window.delayedReload(), void 0;
                var headline, copy;
                config.lessonRole == constants.ROLE.STUDENT ? (headline = "Your lesson space is loading...", copy = "You're not being charged for this time. It won't take long!") : data.tutorAssigned ? (headline = "Your lesson space is loading...", copy = "Hang tight! You'll be there in a matter of seconds.") : (headline = "We're loading your controls", copy = "Just one moment..."), $("#session-loading > h1.headline").html(headline), progress = startProgressBar({
                    bar: document.getElementById("session-loading-bar-progress"),
                    copy: document.getElementById("session-loading-bar-text"),
                    elapsedMs: 1e3 * data.progressBarSeconds,
                    msPerIncrement: 100,
                    steps: [{
                        percent: 5,
                        time: 3e3,
                        copy: copy
                    }, {
                        percent: 50,
                        time: 15e3,
                        copy: copy
                    }, {
                        percent: 70,
                        time: 22e3,
                        copy: copy
                    }, {
                        percent: 100,
                        time: 42e3,
                        copy: copy
                    }]
                })
            },
            backwards: function () {
                window.clearInterval(progress)
            }
        }),
        LoadRetry = DelayedReload,
        StudentLoadFail = Step.extend({
            setDefaults: function () {
                this.elements = ["#session-workspace-container", "#load-fail-container", "#student-load-fail", "#waiting-for-approval-container", "#cover"]
            },
            forwards: function () {
                window.hideLightbox()
            }
        }),
        TutorLoadFail = StudentLoadFail.extend({
            setDefaults: function () {
                this.elements = ["#session-workspace-container", "#load-fail-container", "#tutor-load-fail", "#cover"]
            }
        }),
        Session = Step.extend({
            setDefaults: function () {
                this.elements = ["#session-workspace-container", "#session-in-progress", "#whiteboard-bottom", "#pause-session", "#etherpad-container", "#tabs", "#working-with", "#session-buttons", "#lesson-status-container"]
            },
            backwards: function (data, workspace) {
                var terminal = constants.TERMINAL_STEPS.concat([constants.LESSON_STEP.ENDED]);
                workspace.liveLesson && _(terminal).contains(data.step) && Backbone.trigger("chat:busy", !1)
            },
            forwards: function (data, workspace) {
                data.alert !== !1 && playReadySound(), window.hideLightbox(), workspace.liveLesson && (workspace.emitState(), Backbone.trigger("chat:busy", !0)), lessonConferenceRegion.enable(), config.lessonMedium != constants.LESSON_MEDIUM.TEXT && lessonConferenceRegion.display(), $("#prescheduled-other-party-has-arrived-modal").modal("hide"), workspace.previousStep.id == constants.LESSON_STEP.PAUSED && config.lessonRole == constants.ROLE.STUDENT && ($("#popup-content").html($("#session-resumed-dlg").html()), window.showLightbox())
            }
        }),
        Paused = Step.extend({
            setDefaults: function () {
                this.elements = ["#session-workspace-container", "#whiteboard-bottom", "#session-paused", "#etherpad-container", "#tabs", "#working-with", ".resume-session", "#session-buttons", "#lesson-status-container"]
            },
            forwards: function () {
                return config.lessonRole === constants.ROLE.TUTOR ? (this._setReminder(), void 0) : ($("#popup-content").html($("#session-paused-dlg").html()), window.showLightbox(), void 0)
            },
            backwards: function () {
                config.lessonRole === constants.ROLE.TUTOR && (window.hideLightbox(), $("#popup-close").show(), window.clearTimeout(this.pauseReminder))
            },
            _setReminder: function () {
                this.pauseReminder = window.setTimeout(function () {
                    $("#popup-close").hide(), $("#popup-content").html($("#tutor-session-paused-reminder").html()).find(".keep-paused").on("click", this._keepPaused.bind(this)), window.showLightbox(), chatUtils.playChatSound()
                }.bind(this), 3e5)
            },
            _keepPaused: function () {
                window.hideLightbox(), $("#popup-close").show(), this._setReminder()
            }
        }),
        Suspended = Step.extend({
            setDefaults: function () {
                this.elements = ["#session-workspace-container", "#whiteboard-bottom", "#session-paused", "#etherpad-container", "#tabs", "#working-with", "#session-buttons", "#lesson-status-container"]
            },
            forwards: function (data, workspace) {
                workspace.previousStep.id == constants.LESSON_STEP.SCHEDULE_ATTEMPT ? ($("#popup-content").html($("#error-scheduling-suspended").html()), $("#info_container").hide()) : ($("#popup-content").html($("#error-suspended").html()), $(".student-suspended-end-session").click(function () {
                    workspace.createLessonEvent(constants.LESSON_EVENT.END)
                })), this.removeUserViewingIcon(), workspace.cursor.hide(), window.hideLightboxClose(), window.showLightbox()
            },
            removeUserViewingIcon: function () {
                $(".user-viewing-icon").remove()
            }
        }),
        Voided = Step.extend({
            setDefaults: function () {
                this.elements = ["#post-void-container"]
            },
            forwards: function (data, workspace) {
                return config.lessonRole == constants.ROLE.TUTOR ? (window.delayedReload(), void 0) : (workspace.tokbox && workspace.tokbox.closeStream(), void 0)
            }
        }),
        Ended = Step.extend({
            setDefaults: function () {
                this.elements = ["#session-workspace-container"]
            },
            forwards: function (data, workspace) {
                return workspace.previousStep.id != constants.LESSON_STEP.LESSON ? (window.delayedReload(), void 0) : ($("#lesson-conference").hide(), $("#session-paused").hide(), setupScheduleModal(function () {
                    var seconds = 45;
                    if (config.lessonRole == constants.ROLE.TUTOR) {
                        var $bar = $("#follow-up-progress-bar");
                        $bar.parent().show();
                        var totalSteps = seconds,
                            timer = 1e3,
                            currentStep = 0,
                            modifier = 20;
                        timer /= modifier, totalSteps *= modifier;
                        var increment;
                        increment = function () {
                            $bar.css("width", Math.floor(100 * (++currentStep / totalSteps)) + "%"), totalSteps > currentStep ? studentLessonTimer = setTimeout(increment, timer) : window.delayedReload()
                        }, increment()
                    } else studentLessonTimer = setTimeout(window.delayedReload, 1e3 * seconds)
                }, workspace), void 0)
            }
        }),
        ScheduleAttempt = Step.extend({
            setDefaults: function () {
                this.elements = ["#session-workspace-container"]
            },
            forwards: function (data, workspace) {
                $("#lesson-conference").hide(), setupScheduleModal(function () {
                    clearTimeout(studentLessonTimer), config.lessonRole == constants.ROLE.STUDENT ? scheduleModal.showAddLesson() : (scheduleModal.removeStep("schedule"), scheduleModal.showStep("create"))
                }, workspace)
            }
        }),
        ScheduleCancel = DelayedReload,
        ScheduleSuccess = Step.extend({
            setDefaults: function () {
                this.elements = ["#session-workspace-container"]
            },
            forwards: function (data) {
                checkScheduling(data)
            }
        }),
        Offline = DelayedReload,
        checkScheduling = function (data) {
            scheduleModal && "proposal" in data && scheduleModal.checkProposal(data.proposal)
        },
        setupScheduleModal = function (callback, workspace) {
            scheduleModal ? _.isFunction(callback) && callback() : (scheduleModal = new SessionScheduleView({
                el: $("#schedule-new-lesson"),
                lessonCode: config.lessonCode,
                createEventCallback: workspace.createLessonEvent.bind(workspace),
                isTutor: config.lessonRole == constants.ROLE.TUTOR
            }), scheduleModal.showModal(), _.isFunction(callback) && callback())
        },
        STEPS = {
            0: Offline,
            1: FindingATutor,
            2: ReadyToWork,
            3: WaitingForApproval,
            4: Abandoned,
            5: Timeout,
            6: Canceled,
            7: DelayedReload,
            8: ViewQuestion,
            9: AlreadyTaken,
            101: WaitingForOtherPartyEarly,
            102: WaitingForOtherParty,
            103: WaitingForOtherPartyLate,
            105: OtherPartyHasArrived,
            106: OtherPartyAlreadyHere,
            107: Late,
            108: MissedLesson,
            801: Loading,
            802: LoadRetry,
            803: StudentLoadFail,
            804: TutorLoadFail,
            901: Session,
            902: Paused,
            903: Suspended,
            904: Ended,
            905: Voided,
            950: ScheduleAttempt,
            951: ScheduleCancel,
            952: ScheduleSuccess
        };
    return {
        STEPS: STEPS,
        checkScheduling: checkScheduling
    }
}), define("session/views", ["session/steps", "session/models", "session/chat", "session/socket", "session/video/views", "session/constants", "session/screenshare", "session/paperboard", "session/cursor", "util", "config", "rollbar"], function (steps, models, chat, socket, opentok, constants, screenShare, Paperboard, LessonCursor, util, config, rollbar) {
    var lessonSocket = socket(config.lessonCode),
        loadedTechnology = [],
        failedTechnology = [];
    Backbone.on("loaded-tech", function (tech) {
        _.isArray(tech) ? loadedTechnology = loadedTechnology.concat(tech) : loadedTechnology.push(tech)
    }), Backbone.on("failed-tech", function (tech) {
        _.isArray(tech) ? failedTechnology = failedTechnology.concat(tech) : failedTechnology.push(tech)
    });
    var Workspace = Backbone.View.extend({
            TECHNOLOGY: ["CHAT"],
            currentStep: null,
            previousStep: {},
            session: null,
            loadFailed: !1,
            loadFinished: !1,
            techStatusTimeout: null,
            tokbox: null,
            chat: null,
            screenShare: null,
            loadSessionStartTime: null,
            rejectedQuestion: !1,
            atFault: null,
            initialize: function (opts) {
                if (this.session = new models.Session, this.session.defaultRetryData = {
                    fn: this.session.getSessionStatus.bind(this.session),
                    success: this.getSessionStatusSuccessCbBase.bind(this),
                    errorCb: this.getStatusErrorCb.bind(this),
                    maxRetries: 10
                }, this.viewLesson = "view_lesson" == config.lessonContext, this.liveLesson = !this.viewLesson && !config.isDemoLesson, this.etherpadLoaded = !1, this.ideLoaded = !1, this.$etherpad = $("#etherpad"), this.$ide = $("#ide"), this.$whiteboard = $("#whiteboard"), this.$whiteboard.$bottom = this.$(".paperboard-bottom"), this.$whiteboard.$pagination = this.$(".paperboard-pagination"), this.$whiteboard.$options = this.$(".paperboard-options"), this.chatView = chat($("#chat-container")), this.screenShareView = screenShare(lessonSocket, this.createLessonEvent.bind(this), $("#screensharing-download-modal"), this.liveLesson), this.viewLesson) return this.currentStep = new steps.STEPS[constants.LESSON_STEP.LESSON]({
                    id: constants.LESSON_STEP.LESSON
                }), this.currentStep.forwards({
                    alert: !1
                }, this), this.currentStep.transition(this.previousStep, this), this.setupComponents(opts.lessonCode), void 0;
                config.lessonMedium !== constants.LESSON_MEDIUM.TEXT && this.TECHNOLOGY.push("STREAM_SYS_REQS", "STREAM"), this.setupListeners(), this.emitTabClicked("whiteboard-tab");
                var techStatus = function () {
                    this.loadSessionStartTime = new Date, clearTimeout(this.techStatusTimeout), this.techStatusTimeout = setTimeout(this.checkTechStatus.bind(this), 1e3)
                }.bind(this);
                window.amplify.subscribe("check-tech-status", techStatus), (config.opentok.sessionID || config.opentok.webrtcSessionID || config.isDemoLesson || config.isScheduledLesson || config.isOnDemandLesson && config.lessonRole == constants.ROLE.TUTOR) && techStatus(), this.setupComponents(opts.lessonCode), this.session.getSessionStatus(), setTimeout(this.checkForPollingActivity.bind(this), 1e3), setInterval(this.logPresence, 6e4), this.started = new Date, rollbar.log("Session js loaded at " + this.started)
            },
            setupComponents: function (lessonCode) {
                if (this.chat = this.chatView.model, this.paperboard = new Paperboard(this.$whiteboard, {
                    $pagination: this.$whiteboard.$pagination,
                    $options: this.$whiteboard.$options,
                    readOnly: this.viewLesson
                }, lessonCode), this.cursor = new LessonCursor($("#other-cursor")), !this.viewLesson) {
                    if (this.tokbox = opentok(), config.DEBUG && (window.paperboard = this.paperboard, window.tokbox = this.tokbox), config.lessonStarted || !config.isOnDemandLesson || config.lessonRole != constants.ROLE.STUDENT) {
                        var tokboxConnect = _.after(2, this.tokbox.collection.load.bind(this.tokbox.collection));
                        window.amplify.subscribe("component.paperboard.loaded", tokboxConnect), window.amplify.subscribe("component.chat.loaded", tokboxConnect)
                    }
                    this.cursor.setup(this.paperboard)
                }
                this.paperboard.load(), this.chat.load()
            },
            setupListeners: function () {
                var self = this,
                    evts = {};
                evts["tab.clicked"] = function (data) {
                    self.updateTabs(data)
                }, lessonSocket.subscribe(evts)
            },
            emitState: function () {
                this.getViewedTab(), this.cursor.emit(), this.paperboard.emitPageChange()
            },
            createLessonEvent: function (event) {
                this.session.createLessonEvent(_.extend(this.session.defaultRetryData, {
                    event: event
                }))
            },
            checkTechStatus: function () {
                if (loadedTechnology.length == this.TECHNOLOGY.length) return this.createLessonEvent(constants.LESSON_EVENT.LOAD), rollbar.log("all technology loaded!"), void 0;
                var now = new Date;
                return now - this.loadSessionStartTime < 2e4 ? (this.techStatusTimeout = setTimeout(this.checkTechStatus.bind(this), 1e3), void 0) : (rollbar.log("20 seconds elapsed... registering load failure"), rollbar.log("loadedTechnology:", {
                    loadedTechnology: loadedTechnology
                }), this.loadFailed = !0, failedTechnology.length > 0 ? (rollbar.log("failedTechnology:", {
                    failedTechnology: failedTechnology
                }), this.createLessonEvent(constants.LESSON_EVENT.LOAD_FAIL), void 0) : (this.createLessonEvent(constants.LESSON_EVENT.LOAD_RETRY), void 0))
            },
            logPresence: function () {
                var now = new Date;
                rollbar.log("In session at " + now)
            },
            checkForPollingActivity: function () {
                if (-1 == $.inArray(this.previousStep.id, constants.TERMINAL_STEPS)) {
                    var now = new Date,
                        endTime = this.session.pollEndTime || this.started;
                    return now - endTime > 2e4 && (!this.loadFailed || this.previousStep.id != constants.LESSON_STEP.LOADING) ? (rollbar.log("NO POLLS RECEIVED FOR 20 SECONDS"), window.delayedReload(), void 0) : (setTimeout(this.checkForPollingActivity.bind(this), 1e3), void 0)
                }
            },
            getSessionStatusSuccessCbBase: function (data) {
                var hasPreviousStep = !$.isPlainObject(this.previousStep);
                if (!hasPreviousStep || data.step != this.previousStep.id) {
                    var previousStepString = hasPreviousStep ? constants.LESSON_STEP_STR[this.previousStep.id] : "N/A";
                    rollbar.log(_.sprintf("Step changing from %s to %s", previousStepString, constants.LESSON_STEP_STR[data.step]))
                }
                return this.screenShareView.model.isInactive() && data.step == constants.LESSON_STEP.LESSON ? this.screenShareView.model.setActive() : (data.step == constants.LESSON_STEP.PAUSED || data.step == constants.LESSON_STEP.SUSPENDED) && this.screenShareView.model.emitPause(), this.rejectedQuestion ? (location.href = "/", !0) : this.loadFailed && data.step == constants.LESSON_STEP.LOADING ? (rollbar.log("loadFailed and step == LOADING"), !0) : (-1 != $.inArray(data.step, [constants.LESSON_STEP.LESSON, constants.LESSON_STEP.PAUSED, constants.LESSON_STEP.SUSPENDED]) && $(".session-state-container .tooltip-target").attr("data-original-title", "Tutoring time " + (config.lessonRole == constants.ROLE.STUDENT ? "used" : "counted") + ": " + data.billableMinutes + " min."), data.step == this.previousStep.id ? (this.adjustVideoPosition(data.step), -1 != $.inArray(data.step, constants.SCHEDULING_STEPS) && steps.checkScheduling(data), this.tokbox.collection.updateStreams(data), !1) : (hasPreviousStep && this.previousStep.backwards(data, this), this.currentStep = new steps.STEPS[data.step]({
                    id: data.step
                }), this.currentStep.forwards(data, this), this.currentStep.transition(this.previousStep, this), this.previousStep = this.currentStep, -1 != $.inArray(data.step, constants.TERMINAL_STEPS) ? !0 : (-1 != $.inArray(data.step, constants.LOADING_FINISHED_STEPS) && (this.loadFinished = !0), this.tokbox.collection.updateStreams(data), !1)))
            },
            getStatusErrorCb: function () {
                window.showErrorCatchall()
            },
            isWorkspaceCoverStep: function (step) {
                return -1 != $.inArray(step, constants.WORKSPACE_COVER_STEPS)
            },
            adjustVideoPosition: function (step) {
                return this.tokbox ? step == constants.LESSON_STEP.CANCELED || step == constants.LESSON_STEP.ABANDONED || step == constants.LESSON_STEP.TIMEOUT ? (this.tokbox.hideMyStream(), void 0) : (-1 != $.inArray(step, constants.LOADING_FINISHED_STEPS) && (this.tokbox.resizeWorkspace(), this.tokbox.showMyStream()), void 0) : void 0
            },
            events: {
                "click #start-session": "startSession",
                "click #student-tech-fail-proceed, #tutor-tech-fail-proceed": "ready",
                "click #start-lesson": "readyFromOtherPartyHasArrived",
                "click #student-tech-fail-decline": "studentTechFail",
                "click #tutor-tech-fail-decline": "tutorTechFail",
                "click #end-session": "endSession",
                "click #void-session": "voidSession",
                "click #whats-this": "showPausedInfoDialog",
                "click #pause-session": "pauseSession",
                "click .resume-session": "resumeSession",
                "click #chat-input": "blurWhiteboard",
                "click #editor": "blurChat",
                "click #accept-question": "acceptQuestion",
                "click #reject-question": "rejectQuestion",
                "submit #session-question-form": "submitSessionQuestion",
                "click #tabs a": "clickTab",
                "show #tabs a[href=#etherpad]": "showEtherpad",
                "show #tabs a[href=#whiteboard]": "showWhiteboard",
                "show #tabs a[href=#ide]": "showIDE",
                "click #find-new-tutor": "createPostVoidLesson"
            },
            startSession: function () {
                return this.createLessonEvent(constants.LESSON_EVENT.APPROVE), !1
            },
            ready: function () {
                return this.createLessonEvent(constants.LESSON_EVENT.READY), !1
            },
            readyFromOtherPartyHasArrived: function () {
                return this.createLessonEvent(constants.LESSON_EVENT.READY), $("#prescheduled-other-party-has-arrived-modal").modal("hide"), !1
            },
            studentTechFail: function () {
                return this.atFault = constants.ROLE.STUDENT, this.createLessonEvent(constants.LESSON_EVENT.CANCEL), !1
            },
            tutorTechFail: function () {
                return this.atFault = constants.ROLE.TUTOR, this.createLessonEvent(constants.LESSON_EVENT.CANCEL), !1
            },
            endSession: function () {
                config.lessonRole == constants.ROLE.TUTOR && this.currentStep.id !== constants.LESSON_STEP.SUSPENDED ? ($("#popup-content").html($("#tutor-end-session-confirm-dlg").html()), $(".confirm-end-session").on("click", function () {
                    this._endSession(), window.hideLightbox()
                }.bind(this)), window.showLightbox()) : this._endSession()
            },
            _endSession: function () {
                return $("#end-session").hasClass("demo-disabled") ? (window.location.href = config.BASE_URL, void 0) : (this.screenShareView.model.endShare({
                    lessonEnd: !0
                }), this.createLessonEvent(constants.LESSON_EVENT.END), !1)
            },
            pauseSession: function () {
                if (!$("#pause-session").hasClass("demo-disabled")) {
                    var self = this;
                    $("#popup-content").html($("#pause-session-confirm-dlg").html()), $(".confirm-pause").on("click", function () {
                        window.hideLightbox(), self.createLessonEvent(constants.LESSON_EVENT.PAUSE)
                    }), window.showLightbox()
                }
                return !1
            },
            resumeSession: function () {
                return this.createLessonEvent(constants.LESSON_EVENT.RESUME), !1
            },
            voidSession: function () {
                return $("#void-session").hasClass("demo-disabled") || ($("#popup-content").html($("#void-session-confirm-dlg").html()), $("a.confirm-void").on("click", function () {
                    config.lessonRole == constants.ROLE.TUTOR && (this.screenShareView.model.endShare({
                        lessonEnd: !0
                    }), this.createLessonEvent(constants.LESSON_EVENT.VOID))
                }.bind(this)), window.showLightbox()), !1
            },
            showPausedInfoDialog: function () {
                return $("#popup-content").html($("#session-paused-info-dlg").html()), window.showLightbox(), !1
            },
            acceptQuestion: function () {
                return this.createLessonEvent(constants.LESSON_EVENT.ACCEPT_QUESTION), !1
            },
            rejectQuestion: function () {
                return this.rejectedQuestion = !0, this.createLessonEvent(constants.LESSON_EVENT.REJECT_QUESTION), !1
            },
            submitSessionQuestion: function () {
                var callback = this.submitSessionQuestionSuccess.bind(this);
                return this.session.submitQuestion({
                    data: $("#session-question-form").serialize(),
                    success: callback,
                    error: callback
                }), !1
            },
            submitSessionQuestionSuccess: function () {
                $("#session-question-form").hide(), $("#expert-facepile").addClass("offset3"), $("#expert-ready-to-work").removeClass("expert-ready-to-work-valigned").addClass("offset2"), this.chat.push($("#id_question").val())
            },
            clickTab: function (event) {
                event.preventDefault();
                var $target = $(event.target).closest("a"),
                    tabClicked = $target.prop("id");
                $target.tab("show"), this.emitTabClicked(tabClicked), "whiteboard-tab" == tabClicked ? this.$whiteboard.$bottom.show() : this.$whiteboard.$bottom.hide(), this.cursor.tabChanged(tabClicked.replace("-tab", ""))
            },
            showEtherpad: function () {
                this.etherpadLoaded || (this.etherpadLoaded = !0, this.$etherpad.html('<iframe id="epframe" name="epframe" src="' + window.ETHERPAD_URL + '" width="614" height="605" frameborder="0"></iframe>'))
            },
            showWhiteboard: function () {},
            showIDE: function (event) {
                if (!this.ideLoaded) {
                    this.ideLoaded = !0;
                    var $target = $(event.target).closest("a");
                    this.$ide.html('<iframe id="epframe" name="epframe" src="' + $target.attr("data-url") + '" width="614" height="605" frameborder="0"></iframe>')
                }
            },
            updateTabs: function (data) {
                if (data.id != config.userCode) {
                    var $tab = $("#" + data.tabClicked);
                    $tab.append(config.userPhotos[data.id]), $tab.find("i").tooltip()
                }
            },
            emitTabClicked: function (tabClicked) {
                lessonSocket.emitToOthers("tab.clicked", {
                    tabClicked: tabClicked,
                    id: config.userCode
                })
            },
            getViewedTab: function () {
                var $activeTab = $("#tabs").find("li.active a"),
                    tabClicked = $activeTab.exists() ? $activeTab.attr("id") : "whiteboard-tab";
                this.emitTabClicked(tabClicked)
            },
            blurWhiteboard: function () {
                this.paperboard.blur()
            },
            blurChat: function () {
                $("#chat-input").blur()
            },
            createPostVoidLesson: function () {
                window.createLesson({
                    lastLessonCode: config.lessonCode,
                    isForwardedFrom: !0
                })
            }
        }),
        TutorMessageModal = Backbone.View.extend({
            events: {
                "click #send": "submit"
            },
            initialize: function (opts) {
                this.submitURL = opts.submitURL, this.successURL = opts.successURL, this.$form = this.$("form"), this.$button = this.$("button")
            },
            submit: function (evt) {
                return util.API.formSubmit(this.$form, evt, {
                    endpoint: this.submitURL,
                    $btn: this.$button,
                    redirects: !0,
                    ajaxOptions: {
                        csrf: !0,
                        success: function () {
                            window.location = this.successURL
                        }.bind(this)
                    }
                }), !1
            }
        });
    return {
        Workspace: Workspace,
        TutorMessageModal: TutorMessageModal,
        BackspaceModal: util.BackspaceModal
    }
}), define("session/chat", ["session/constants", "session/socket", "chat/config", "chat/view-utils", "util", "rollbar", "config"], function (constants, socket, chatConfig, chatUtils, util, rollbar, config) {
    var lessonSocket = socket(config.lessonCode),
        Chat = Backbone.Model.extend({
            defaults: {
                attachment: null
            },
            initialize: function () {
                this.pushEndpoint = "/s/" + config.lessonCode + "/chat/", this.uploadEndpoint = "/s/" + config.lessonCode + "/chat-upload/", this.lessonCode = config.lessonCode, this.question = config.question
            },
            load: function () {
                rollbar.log("startChat"), this.initSocket(), this.initData(), window.amplify.publish("component.chat.loaded")
            },
            initSocket: function () {
                var evts = {},
                    self = this,
                    other = config.lessonRole == constants.ROLE.TUTOR ? constants.ROLE.STUDENT : constants.ROLE.TUTOR;
                evts[lessonSocket.room + ".chat"] = function (data) {
                    self.trigger("message.new", data)
                }, evts["typing:user=" + other] = function () {
                    self.trigger("typing.started")
                }, evts["stopped-typing:user=" + other] = function (textEntered) {
                    self.trigger("typing.stopped", textEntered)
                }, lessonSocket.subscribe(evts)
            },
            initData: function () {
                var self = this;
                util.API.get(this.pushEndpoint, {
                    success: function (data) {
                        self.loadSuccess(), _.each(data.messages, function (item) {
                            self.trigger("message.new", _.extend(item, {
                                init: !0
                            }))
                        })
                    }
                })
            },
            loadSuccess: function () {
                Backbone.trigger("loaded-tech", "CHAT"), this.question && this.push(this.question)
            },
            push: function (message) {
                var data = {
                    body: message || ""
                };
                return this.hasAttachment() && (data.attachment = this.getAttachment().id, this.setAttachment(null)), _.isBlank(data.body) && !data.attachment ? !1 : util.API.post(this.pushEndpoint, {
                    csrf: !0,
                    data: data,
                    checkDataForDoubleSubmit: !0
                })
            },
            hasAttachment: function () {
                return !_.isNull(this.getAttachment())
            },
            getAttachment: function () {
                return this.get("attachment")
            },
            setAttachment: function (attachment) {
                this.set("attachment", attachment)
            },
            startTyping: function () {
                lessonSocket.emitToRoom("typing:user=" + config.lessonRole)
            },
            stopTyping: function (textEntered) {
                lessonSocket.emitToRoom("stopped-typing:user=" + config.lessonRole, textEntered)
            }
        }),
        LessonChat = Backbone.Marionette.View.extend({
            ui: {
                attachButton: ".chat-attach-button",
                attachDialog: ".chat-file-dialog",
                attachFile: ".chat-file",
                attachProgress: ".chat-attach-progress",
                attachProgressBar: ".chat-attach-progress .bar",
                attachText: ".chat-textarea-attachment",
                form: "#chat-form",
                typingMessage: ".typing-message",
                textEnteredMessage: ".text-entered-message",
                textarea: ".input-widget",
                messages: "#ta-widget",
                messageList: ".message-list",
                sendButton: ".send-button-container button",
                enterToSend: ".send-button-container input"
            },
            events: {
                "keydown .input-widget": "chatKeydown",
                "keyup .input-widget": "chatKeyup",
                "click .send-button-container input": "toggleEnterToSend",
                "click .send-button-container button": "sendMessage",
                "click .chat-attach-button": "toggleAttachment",
                "dblclick .chat-attach-button": "preventToggle"
            },
            modelEvents: {
                "typing.started": "typingStarted",
                "typing.stopped": "typingStopped",
                "message.new": "newMessageHandler",
                "change:attachment": "attachmentChanged"
            },
            initialize: function () {
                this.bindUIElements(), this.typingTimeout = null, this.startTyping = _.debounce(this.model.startTyping.bind(this.model), 250, !0), this.msgTemplate = _.template(this.$("#lesson-chat-template").html()), this.setupFileUpload(), this.attachmentChanged()
            },
            setupFileUpload: function () {
                var self = this;
                util.fileUpload(this.ui.form, {
                    url: this.model.uploadEndpoint,
                    afterChange: function (e, data) {
                        self.ui.attachText.hide(), data.context.hasAttachment || self.model.setAttachment(null)
                    },
                    beforeAdd: function () {
                        self.fileUploading = !0
                    },
                    beforeFail: function (e, data) {
                        400 == data.jqXHR.status && (self.ui.attachText.html("").hide(), self.model.setAttachment(null))
                    },
                    always: function () {
                        self.ui.attachFile.show(), self.ui.attachProgress.hide(), self.fileUploading = !1
                    },
                    afterProgress: function () {
                        self.ui.attachFile.hide()
                    }
                })
            },
            attachmentChanged: function () {
                this.model.hasAttachment() ? (this.ui.textarea.attr("placeholder", ""), this.ui.attachText.show(), this.adjustAttachmentIndent()) : (this.ui.textarea.attr("placeholder", this.ui.textarea.data("placeholder")), this.ui.attachText.hide(), this.ui.attachFile.val(""), this.adjustAttachmentIndent(!0))
            },
            adjustAttachmentIndent: function (reset) {
                reset ? this.ui.textarea.css("text-indent", 0) : this.ui.textarea.css("text-indent", this.ui.attachText.outerWidth())
            },
            toggleAttachment: function () {
                if (this.ui.attachButton.toggleClass("pressed"), this.ui.attachDialog.is(":visible")) this.ui.attachDialog.hide();
                else {
                    this.ui.attachDialog.show();
                    var removeClick, self = this;
                    removeClick = function () {
                        $("body").one("click", function (event) {
                            return $(event.target).hasClass("chat-file") ? (removeClick(), !0) : (self.ui.attachDialog.hide(), self.ui.attachButton.removeClass("pressed"), void 0)
                        })
                    }, removeClick()
                }
                return !1
            },
            preventToggle: function (event) {
                event.stopPropagation()
            },
            toggleEnterToSend: function () {
                this.ui.enterToSend.is(":checked") ? this.ui.sendButton.fadeOut() : this.ui.sendButton.fadeIn()
            },
            sendMessage: function () {
                return this.send(), this.stopTyping(), !1
            },
            chatKeydown: function (event) {
                return util.isEnterKey(event) && this.ui.enterToSend.is(":checked") && !event.shiftKey ? (this.sendMessage(), !1) : (this.model.hasAttachment() && _.isBlank(this.ui.textarea.val()) && event.keyCode == util.Event.KEY_BACK_SPACE && this.model.setAttachment(null), void 0)
            },
            chatKeyup: function () {
                var text = this.ui.textarea.val();
                _.isBlank(text) ? this.stopTyping() : (this.startTyping(), clearTimeout(this.typingTimeout), this.typingTimeout = setTimeout(this.stopTyping.bind(this), 3e3))
            },
            stopTyping: function () {
                clearTimeout(this.typingTimeout);
                var text = this.ui.textarea.val();
                this.model.stopTyping(!_.isBlank(text))
            },
            typingStarted: function () {
                this.ui.textEnteredMessage.hide(), this.ui.typingMessage.show(), this.addPadding()
            },
            typingStopped: function (textEntered) {
                this.ui.typingMessage.hide(), this.ui.textEnteredMessage[textEntered ? "show" : "hide"](), textEntered ? this.addPadding() : this.removePadding()
            },
            addPadding: function () {
                this.ui.messages.find(".chat-padding").exists() || (this.ui.messages.append($('<div class="chat-padding">&nbsp;</div>')), this.scrollConversation())
            },
            removePadding: function () {
                this.ui.messages.find(".chat-padding").remove(), this.scrollConversation()
            },
            scrollConversation: function () {
                this.ui.messages.scrollTop(this.ui.messages.prop("scrollHeight"))
            },
            getSenderName: function (senderRole) {
                var tutorName = $(".tutor-name").first().text(),
                    studentName = $(".student-name").first().text(),
                    senderName = studentName;
                return config.lessonRole == senderRole ? senderName = "Me" : config.lessonRole == constants.ROLE.STUDENT && (senderName = tutorName), senderName
            },
            newMessageHandler: function (data) {
                var isSender = data.user == config.lessonRole,
                    onBottom = this.ui.messages.isOnBottom(),
                    isSystemMessage = _.isNull(data.user);
                (!isSender || data.init) && (isSystemMessage ? this.insertSystemMessage({
                    text: data.msg
                }) : this.insertChatMessage({
                    sent: isSender,
                    senderRole: data.user,
                    messageText: data.msg,
                    attachment: data.attachment
                }), onBottom && this.ui.messages.scrollToBottom()), config.lessonRole == constants.ROLE.STUDENT && data.msg == this.question && (this.question = null)
            },
            insertSystemMessage: function (message) {
                var html = this.msgTemplate({
                    className: "system-message",
                    message: _.nl2br(_.linkify(_.escape(message.text), !0)),
                    senderName: null,
                    attachment: null
                });
                this.ui.messageList.append(html), this._playChatSound()
            },

            _playChatSound: function () {
                chatConfig.soundsEnabled() && !document.hasFocus() && chatUtils.playChatSound()
            },
            send: function () {
                var message = this.ui.textarea.val(),
                    attachment = this.model.getAttachment();
                this.model.push(message) && (this.insertChatMessage({
                    sent: !0,
                    senderRole: config.lessonRole,
                    messageText: message,
                    attachment: attachment
                }), this.ui.messages.scrollToBottom(), this.ui.form[0].reset(), this.ui.textarea.val(""))
            }
        });
    return function ($el) {
        return new LessonChat({
            el: $el,
            model: new Chat
        })
    }
}), define("session/screenshare", ["session/constants", "util", "config", "rollbar"], function (constants, util, config, rollbar) {
    var SHARE_STATES = {
            IDLE: {
                tooltip: "You can share all or just part of your screen. Your screen share will begin in a paused state so you can choose what you'd like to share.",
                delay: 1e3,
                disabled: !1,
                "class": "idle"
            },
            PRE_LESSON: {
                tooltip: "Once the lesson begins, you will be able to share your screen with the other party.",
                delay: 0,
                disabled: !0,
                "class": "pre-lesson"
            },
            PAUSED: {
                tooltip: "Once the lesson resumes, you will be able to share your screen with the other party.",
                delay: 0,
                disabled: !0,
                "class": "paused"
            },
            DEMO: {
                tooltip: "In a live lesson, this tool launches a screen sharing session that allows you to share all or part of your screen with the other party.",
                delay: 0,
                disabled: !0,
                "class": "demo"
            },
            PRESENTING: {
                action: "Stop Sharing Screen",
                text: "You are sharing your screen",
                "class": "presenting"
            },
            VIEWING: {
                action: "Leave Screenshare",
                text: "Viewing shared screen",
                "class": "viewing"
            },
            DOWNLOADING: {
                text: "Download...",
                action: "Cancel",
                "class": "downloading"
            },
            OTHER_DOWNLOAD: {
                text: "Waiting for other party to set up",
                action: "Cancel",
                "class": "other-download"
            },
            SCREENSHARE_PAUSED_PRESENTER: {
                action: "Stop Sharing Screen",
                text: "Screenshare is Paused",
                "class": "paused"
            },
            SCREENSHARE_PAUSED_VIEWER: {
                action: "Leave Screenshare",
                text: "Screenshare is Paused",
                "class": "paused"
            },
            SCREENSHARE_PAUSED_INIT: {
                action: "Leave Screenshare",
                text: "Screenshare is Paused",
                "class": "paused"
            },
            LESSON_ENDED: {}
        },
        BUTTON_STATES = [SHARE_STATES.PAUSED, SHARE_STATES.IDLE, SHARE_STATES.DEMO, SHARE_STATES.PRE_LESSON],
        ScreenState = Backbone.Model.extend({
            defaults: {
                isPresenter: !1,
                liveLesson: null,
                screenShareData: null,
                viewerURL: "",
                error: !1,
                shareState: config.isDemoLesson ? SHARE_STATES.DEMO : SHARE_STATES.PRE_LESSON
            },
            initialize: function (options) {
                this.lessonSocket = options.socket, this.getLiveLesson() && this.initSocket()
            },
            initSocket: function () {
                this.lessonSocket.subscribe({
                    screenshareInit: function (data) {
                        this.getIsPresenter() ? this.setShareState(SHARE_STATES.SCREENSHARE_PAUSED_PRESENTER) : (this.setShareState(SHARE_STATES.SCREENSHARE_PAUSED_INIT), this.setViewerURL(data.viewerUrl))
                    }.bind(this),
                    screenshareEnd: function (data) {
                        var stateUpdate = function (data) {
                            this.setIsPresenter(!1), this.setShareState(data.lessonEnd ? SHARE_STATES.LESSON_ENDED : SHARE_STATES.IDLE)
                        }.bind(this);
                        this.getIsPresenter() && data.endSession && this.endScreenShare(), stateUpdate(data)
                    }.bind(this),
                    screenshareDownload: function () {
                        this.getIsPresenter() ? this.setShareState(SHARE_STATES.DOWNLOADING) : this.setShareState(SHARE_STATES.OTHER_DOWNLOAD)
                    }.bind(this),
                    setPause: function () {
                        this.setShareState(SHARE_STATES.PAUSED)
                    }.bind(this),
                    screensharePause: function () {
                        this.getIsPresenter() ? this.setShareState(SHARE_STATES.SCREENSHARE_PAUSED_PRESENTER) : this.setShareState(SHARE_STATES.SCREENSHARE_PAUSED_VIEWER)
                    }.bind(this),
                    screenshareResume: function () {
                        this.getIsPresenter() ? this.setShareState(SHARE_STATES.PRESENTING) : this.setShareState(SHARE_STATES.VIEWING)
                    }.bind(this)
                })
            },
            getIsPresenter: function () {
                return this.get("isPresenter")
            },
            setIsPresenter: function (isPresenter) {
                this.set("isPresenter", !!isPresenter)
            },
            getError: function () {
                return this.get("error")
            },
            setError: function (error) {
                this.set("error", error)
            },
            getLiveLesson: function () {
                return this.get("liveLesson")
            },
            emitPause: function () {
                this.lessonSocket.emitToRoom("setPause")
            },
            getShareState: function () {
                return this.get("shareState")
            },
            setShareState: function (state) {
                this.set("shareState", state)
            },
            isInactive: function () {
                return this.getShareState().disabled
            },
            setActive: function () {
                config.isDemoLesson || this.setShareState(SHARE_STATES.IDLE)
            },
            getViewerURL: function () {
                return this.get("viewerURL")
            },
            setViewerURL: function (url) {
                this.set("viewerURL", url)
            },
            getScreenShareData: function () {
                return this.get("screenShareData")
            },
            setScreenShareData: function (data) {
                this.set("screenShareData", data)
            },
            endScreenShare: function () {
                util.API.post("end-screenshare/", {
                    data: {
                        screenShareCode: this.getScreenShareData().screenShareCode
                    },
                    csrf: !0,
                    error: function () {
                        rollbar.error("Error ending screenshare state")
                    }
                })
            },
            toggleShare: function () {
                this.getShareState() == SHARE_STATES.IDLE && (this.setIsPresenter(!0), util.API.post("initialize-screenshare/", {
                    csrf: !0,
                    data: {
                        externalID: config.lessonCode
                    },
                    success: function (data) {
                        var screenShareData = {
                            id: config.userCode
                        };
                        _.extend(screenShareData, data), this.setScreenShareData(screenShareData), this.setShareState(SHARE_STATES.SCREENSHARE_PAUSED_PRESENTER), window.screenleap.startSharing("NATIVE", screenShareData)
                    }.bind(this),
                    error: function () {
                        this.setError(!0)
                    }.bind(this)
                }))
            },
            acceptShare: function () {
                window.open(this.getViewerURL(), "_blank"), this.setViewerURL("")
            },
            endShare: function (data) {
                data.modal && this.setViewerURL(""), this.lessonSocket.emitToRoom("screenshareEnd", data)
            }
        }),
        ScreenShareView = Backbone.Marionette.View.extend({
            ui: {
                button: "#screensharing-button",
                status: "#screensharing-status",
                statusText: "#screensharing-status span",
                statusAction: "#screensharing-status a",
                modal: "#screensharing-accept-modal",
                errorModal: "#screensharing-error-modal",
                downloadModal: "#screensharing-download-modal"
            },
            events: {
                "click #screensharing-button": "toggleShare",
                "click .screenshare-action": "endShare",
                "click .accept": "acceptShare",
                "click .no-thanks": "denyShare"
            },
            modelEvents: {
                "change:shareState": "renderStatus",
                "change:error": "renderError"
            },
            initialize: function () {
                this.bindUIElements(), this.renderStatus()
            },
            toggleShare: function () {
                this.model.isInactive() || this.model.toggleShare()
            },
            endShare: function () {
                this.model.endShare({
                    lessonEnd: !1,
                    endSession: !0
                })
            },
            acceptShare: function () {
                this.model.acceptShare(), this.ui.modal.modal("hide")
            },
            denyShare: function () {
                this.model.endShare({
                    lessonEnd: !1,
                    modal: !0,
                    endSession: !0
                }), this.ui.modal.modal("hide")
            },
            renderError: function () {
                this.model.getError() && (this.ui.errorModal.modal(), this.model.setError(!1))
            },
            renderStatus: function () {
                var state = this.model.getShareState();
                this.ui.status.removeClass(), this.ui.status.addClass(state.class), _(BUTTON_STATES).contains(state) ? (this.ui.status.hide(), this.ui.button.removeClass("disabled"), this.ui.button.data("tooltip", !1), this.ui.button.tooltip({
                    delay: {
                        show: state.delay
                    },
                    placement: "bottom",
                    title: state.tooltip
                }), state.disabled && this.ui.button.addClass("disabled"), this.ui.button.show()) : state === SHARE_STATES.LESSON_ENDED ? (this.ui.button.hide(), this.ui.status.hide()) : (state === SHARE_STATES.SCREENSHARE_PAUSED_INIT ? this.ui.modal.modal({
                    keyboard: !1,
                    backdrop: "static"
                }) : state === SHARE_STATES.SCREENSHARE_PAUSED_PRESENTER && this.ui.downloadModal.modal("hide"), this.ui.button.hide(), this.ui.statusText.text(state.text), this.ui.statusAction.text(state.action), this.ui.status.data("tooltip", !1), this.ui.status.tooltip({
                    placement: "bottom",
                    title: state.tooltip
                }), this.ui.status.show())
            }
        }),
        screenleapCallbacks = function (lessonSocket, createLessonEvent, screenShareView) {
            return {
                onScreenShareStart: function () {
                    lessonSocket.emitToRoom("screenshareInit", screenShareView.model.getScreenShareData()), createLessonEvent(constants.LESSON_EVENT.SCREEN_START), setTimeout(createLessonEvent(constants.LESSON_EVENT.SCREEN_PAUSE), 30)
                },
                onScreenShareEnd: function () {
                    lessonSocket.emitToRoom("screenshareEnd", {
                        lessonEnd: !1,
                        endSession: !1
                    }), createLessonEvent(constants.LESSON_EVENT.SCREEN_END)
                },
                onAppDownloadStart: function () {
                    screenShareView.ui.downloadModal.modal(), lessonSocket.emitToRoom("screenshareDownload")
                },
                onPause: function () {
                    lessonSocket.emitToRoom("screensharePause"), createLessonEvent(constants.LESSON_EVENT.SCREEN_PAUSE)
                },
                onResume: function () {
                    lessonSocket.emitToRoom("screenshareResume"), createLessonEvent(constants.LESSON_EVENT.SCREEN_RESUME)
                },
                error: function (action, errorMessage) {
                    rollbar.error("screenleap error: " + errorMessage + "action: " + action)
                }
            }
        };
    return function (socket, createLessonEvent, downloadModal, liveLesson) {
        var view = new ScreenShareView({
            el: "#screensharing",
            model: new ScreenState({
                socket: socket,
                liveLesson: liveLesson
            }),
            downloadModal: downloadModal
        });
        return _.extend(window.screenleap, screenleapCallbacks(socket, createLessonEvent, view)), view
    }
}), define("session/audiobridge/views", ["session/models", "session/managers", "session/constants", "config"], function (models, managers, constants, config) {
    var LessonConferenceInfoView = Backbone.Marionette.ItemView.extend({
            template: "#lesson-conference-info-template",
            events: {
                "click .show-how-it-works-modal": "showHowItWorksModal"
            },
            showHowItWorksModal: function () {
                this.trigger("show-how-it-works-modal")
            }
        }),
        LessonConferenceToggleView = Backbone.Marionette.ItemView.extend({
            events: {
                "click .show-content": "showContent",
                "click .hide-content": "hideContent",
                "click .create-call": "createCall",
                "click .show-how-it-works-modal": "showHowItWorksModal"
            },
            ui: {
                showContent: "#conference-show-content",
                content: "#conference-initiate"
            },
            template: "#lesson-conference-toggle-template",
            initialize: function (options) {
                this.region = options.region, this.contentShown = !1, this.listenTo(this.region, "forceHideContent", this.hideContent)
            },
            createCall: function () {
                this.model.emitCreateCall(), this.model.setConferenceInfo()
            },
            showContent: function () {
                this.toggleContent(), this.trigger("showContent")
            },
            hideContent: function () {
                this.contentShown && this.toggleContent()
            },
            toggleContent: function () {
                this.contentShown = !this.contentShown, this.ui.showContent.toggle(), this.ui.content.toggle(), this.trigger("toggleContent")
            },
            showHowItWorksModal: function () {
                this.region.showHowItWorksModal()
            }
        }),
        LessonConferenceRegion = Backbone.Marionette.Region.extend({
            el: "#lesson-conference",
            initialize: function () {
                if (this.removedFromChat = 0, this.hidden = config.lessonMedium == constants.LESSON_MEDIUM.TEXT, this.enabled = config.lessonMedium != constants.LESSON_MEDIUM.TEXT, this.howItWorksModal = $("#lesson-conference-how-it-works"), this.modalInstructionsTemplate = _.template($("#post-conference-instructions-template").html()), this.model = new models.LessonConference, this.listenTo(this.model, "change:code", function () {
                    this.hidden && this.display(), this.showLessonConferenceInfo()
                }), config.lessonConferenceCode) this.model.set({
                    phone: config.lessonConferencePhoneNumber,
                    code: config.lessonConferenceCode
                });
                else {
                    var view = new LessonConferenceToggleView({
                        model: this.model,
                        region: this
                    });
                    this.show(view), this.listenTo(view, "showContent", function () {
                        this.trigger("expandToggleView")
                    }.bind(this)), this.listenTo(view, "toggleContent", this.resizeChat)
                }
            },
            enable: function () {
                this.enabled = !0
            },
            getHeight: function () {
                return this.hidden && !config.lessonConferenceCode ? 0 : this.$el.is(":hidden") ? config.lessonConferenceCode ? 53 : 22 : this.$el.outerHeight()
            },
            resizeChat: function () {
                var heightDelta = this.getHeight() - this.removedFromChat;
                0 !== heightDelta && (managers.chatManager.updateHeight(heightDelta), this.removedFromChat += heightDelta)
            },
            showHowItWorksModal: function () {
                this.model.has("code") && this.howItWorksModal.find(".levered-instructions").html(this.modalInstructionsTemplate(this.model.attributes)), this.howItWorksModal.modal("show")
            },
            showLessonConferenceInfo: function () {
                var view = new LessonConferenceInfoView({
                    model: this.model,
                    region: this
                });
                this.listenTo(view, "show-how-it-works-modal", this.showHowItWorksModal), this.show(view)
            },
            forceHideContent: function () {
                this.trigger("forceHideContent")
            },
            onShow: function () {
                this.resizeChat()
            },
            display: function () {
                this.$el && (this.$el.show(), this.hidden = !1, this.resizeChat())
            },
            hide: function () {
                this.$el.hide(), this.hidden = !0, this.resizeChat()
            }
        });
    return new LessonConferenceRegion
}), define("session/video/models", ["session/socket", "rollbar", "config", "session/constants", "events", "util"], function (socket, rollbar, config, constants, events, util) {
    var lessonSocket = socket(config.lessonCode),
        Stream = Backbone.Model.extend({
            defaults: {
                user: null,
                stream: null,
                published: !1,
                registered: !1,
                maximized: !1,
                userMinimized: !1,
                viewedNote: null,
                hasAudio: !1,
                hasVideo: !1
            },
            initialize: function () {
                this._storeKey = "lessonVA" + config.lessonCode + this.get("user"), this.autosave()
            },
            fetch: function (data) {
                var stored = window.amplify.store(this._storeKey);
                stored && this.set(stored), data && this.set(data)
            },
            sync: function (method, model, options) {
                var expiration = 108e5;
                switch (method) {
                case "create":
                case "update":
                    window.amplify.store(this._storeKey, model.toJSON(), {
                        expires: expiration
                    });
                    break;
                case "delete":
                    window.amplify.store(this._storeKey, null)
                }
                options && options.success(window.amplify.store(this._storeKey))
            },
            toJSON: function () {
                var json = Backbone.Model.prototype.toJSON.call(this);
                return _.each(["id", "stream", "registered"], function (field) {
                    delete json[field]
                }), _.each(this.defaults, function (def, key) {
                    json[key] === def && delete json[key]
                }), json
            },
            reset: function () {
                this.setStream(null), this.set({
                    published: !1,
                    registered: !1
                })
            },
            triggerChanges: function () {
                _.each(this.attributes, function (value, key) {
                    this.trigger("change:" + key, this, value)
                }.bind(this))
            },
            maximize: function () {
                this.set("maximized", !0), this.set("userMinimized", !1)
            },
            minimize: function (manual) {
                this.set("maximized", !1), this.set("userMinimized", !!manual)
            },
            register: function () {
                this.set("registered", !0)
            },
            setStream: function (stream) {
                this.set("stream", stream), this.hasAudio(stream && stream.hasAudio), this.hasVideo(stream && stream.hasVideo)
            },
            getStream: function () {
                return this.get("stream")
            },
            publish: function () {
                this.set("published", !0)
            },
            isPublished: function () {
                return !!this.get("published")
            },
            isRegistered: function () {
                return !!this.get("registered")
            },
            isMaximized: function () {
                return !!this.get("maximized")
            },
            isMinimized: function () {
                return !this.isMaximized()
            },
            isUserMinimized: function () {
                return !!this.get("userMinimized")
            },
            viewedNote: function (viewed) {
                return _.isUndefined(viewed) || this.set("viewedNote", !!viewed), this.get("viewedNote")
            },
            hasVideo: function (video) {
                return _.isUndefined(video) || this.set("hasVideo", !!video), !!this.get("hasVideo")
            },
            hasAudio: function (audio) {
                return _.isUndefined(audio) || this.set("hasAudio", !!audio), !!this.get("hasAudio")
            },
            hasAudioOrVideo: function () {
                return this.hasAudio() || this.hasVideo()
            },
            enableVideo: function () {
                this.trigger("video", !0)
            },
            disableVideo: function () {
                this.trigger("video", !1)
            },
            enableAudio: function () {
                this.trigger("audio", !0)
            },
            disableAudio: function () {
                this.trigger("audio", !1)
            }
        }),
        Opentok = Backbone.Collection.extend({
            model: Stream,
            initialize: function () {
                this.config = config.opentok, this.setupVars(), lessonSocket.subscribe({
                    webrtc: this.toggleWebRTC.bind(this)
                })
            },
            setupVars: function () {
                this.session = null, this.publisher = null, this.connectionID = null, this.webrtcSet = new $.Deferred, this.sessionCreated = new $.Deferred, this.hasRequirements = !1, this.loading = !1, this.loaded = !1, this.registering = !1, this.loadVideoStarted = !1, this.tokenRetries = 0, this.registerRetries = 0, this.connectTimeout = null
            },
            toggleWebRTC: function (enable) {
                this.config.webrtc != enable && (enable && !this.config.webrtcCapable ? this.config.webrtc = !1 : (rollbar.log("Changing webrtc status to " + (enable ? "true" : "false")), this.config.webrtc = enable, this.loaded && this.reload()), this.sendTechStatus()), this.webrtcSet.resolve()
            },
            sendWebRTCStatus: function () {
                lessonSocket.webrtc(this.config.webrtcCapable)
            },
            sendTechStatus: function () {
                this.myStream && this.myStream.trigger("technology", this.config.webrtc ? "webrtc" : "flash")
            },
            disconnect: function () {
                this.session && this.session.disconnect()
            },
            reload: function () {
                this.disconnect(), this.config.token = null, window.TB = null, this.reset(), this.myStream && this.myStream.reset(), this.setupVars(), this.load()
            },
            load: function () {
                config.isDemoLesson || config.isOnDemandLesson && config.isCandidate ? this.webrtcSet.resolve() : this.sendWebRTCStatus(), this.webrtcSet.done(function () {
                    if (!this.loaded && !this.loading) {
                        this.loading = !0, rollbar.log("loadTokbox");
                        var urls = {
                                flash: "https://static.opentok.com/v1.1/js/TB.min.js",
                                webrtc: "https://static.opentok.com/webrtc/v2.0/js/TB.min.js"
                            },
                            opentokURL = this.config.webrtc ? urls.webrtc : urls.flash;
                        $.ajax({
                            url: opentokURL,
                            dataType: "script",
                            cache: !0,
                            success: function () {
                                window.TB.setLogLevel(config.DEBUG ? window.TB.DEBUG : window.TB.INFO), this.loaded = !0, this.hasRequirements = window.TB.checkSystemRequirements(), config.lessonMedium !== constants.LESSON_MEDIUM.TEXT && (this.hasRequirements ? Backbone.trigger("loaded-tech", "STREAM_SYS_REQS") : Backbone.trigger("failed-tech", ["STREAM_SYS_REQS", "STREAM"])), this.startConnect()
                            }.bind(this),
                            error: function () {
                                config.lessonMedium !== constants.LESSON_MEDIUM.TEXT && (rollbar.error("Failed to load opentok javascript"), Backbone.trigger("failed-tech", ["STREAM_SYS_REQS", "STREAM"]))
                            },
                            complete: function () {
                                this.loading = !1
                            }.bind(this)
                        })
                    }
                }.bind(this))
            },
            startConnect: function () {
                if (!this.loadVideoStarted) {
                    if (this.loadVideoStarted = !0, this.config.token && this.getSessionID()) return rollbar.log("token = " + this.config.token), this.connect(), void 0;
                    rollbar.log("Generating opentok token");
                    var ts = (new Date).getTime().toString();
                    return util.API.post(config.GENERATE_OPENTOK_TOKEN_URL + "?_=" + ts, {
                        csrf: !0,
                        data: {
                            webrtc: this.config.webrtc ? 1 : 0
                        },
                        success: function (data) {
                            this.config.sessionID = data.flashSessionID, this.config.webrtcSessionID = data.webrtcSessionID, this.config.token = data.opentokToken, this.connect()
                        }.bind(this),
                        error: function () {
                            ++this.tokenRetries <= 5 ? (rollbar.error("Failed to generate opentok token"), setTimeout(this.startConnect.bind(this), 5e3)) : rollbar.error("Failed final attempt to generate opentok token")
                        }.bind(this),
                        complete: function () {
                            this.loadVideoStarted = !1
                        }.bind(this)
                    })
                }
            },
            connect: function () {
                if (!this.hasRequirements) return rollbar.warn("skipping loadVideo - opentok system requirements not met."), void 0;
                var sessionID = this.getSessionID();
                return this.config.token && sessionID ? (rollbar.log("loadVideo - connecting to sessionID " + sessionID), window.TB.addEventListener("exception", this.exceptionHandler.bind(this)), this.session = window.TB.initSession(sessionID), this.session.addEventListener("sessionConnected", this.sessionConnectedHandler.bind(this)), this.session.addEventListener("sessionDisconnected", this.sessionDisconnectedHandler.bind(this)), this.session.addEventListener("connectionCreated", this.connectionCreatedHandler.bind(this)), this.session.addEventListener("connectionDestroyed", this.connectionDestroyedHandler.bind(this)), this.session.addEventListener("streamCreated", this.streamCreatedHandler.bind(this)), this.session.addEventListener("streamDestroyed", this.streamDestroyedHandler.bind(this)), this.session.addEventListener("streamPropertyChanged", this.streamPropertyChangedHandler.bind(this)), this.session.connect(this.config.apiKey, this.config.token), void 0) : (rollbar.warn("skipping loadVideo - no token or session available."), void 0)
            },
            sessionConnectedHandler: function (event) {
                rollbar.log("sessionConnectedHandler"), this.connectionID = this.session.connection.connectionId, this.sessionCreated.resolve(), this.subscribeToStreams(event.streams), this.myStream.trigger("session:connected"), Backbone.trigger("loaded-tech", "STREAM")
            },
            sessionDisconnectedHandler: function () {
                rollbar.log("sessionDisconnectedHandler")
            },
            connectionCreatedHandler: function () {
                rollbar.log("connectionCreatedHandler")
            },
            connectionDestroyedHandler: function () {
                rollbar.log("connectionDestroyedHandler")
            },
            streamCreatedHandler: function (event) {
                rollbar.log("streamCreatedHandler"), this.trigger("stream:created"), this.subscribeToStreams(event.streams)
            },
            streamDestroyedHandler: function (event) {
                rollbar.log("streamDestroyedHandler"), _.each(event.streams, function (stream) {
                    var model = this.get(stream.connection.connectionId);
                    model && (model.setStream(null), model.minimize())
                }.bind(this))
            },
            streamPropertyChangedHandler: function (event) {
                var stream = event.stream;
                rollbar.log("streamPropertyChangedHandler"), rollbar.log(event.changedProperty + "	" + event.oldValue + " --> " + event.newValue);
                var model = this.get(stream.connection.connectionId);
                model && (model.setStream(stream), model.id == this.myStream.id || model.hasAudio() || model.hasVideo() || model.minimize())
            },
            exceptionHandler: function (event) {
                rollbar.error("exceptionHandler: " + event.title + " (" + event.code + ") - " + event.message + " [token = " + this.config.token + "]"), (1006 === event.code || 1008 === event.code || 1014 === event.code) && this.config.token && this.getSessionID() && (clearTimeout(this.connectTimeout), this.connectTimeout = setTimeout(function () {
                    this.session.connect(this.config.apiKey, this.config.token)
                }.bind(this), 5e3))
            },
            addMyStream: function (model) {
                this.myStream = model, this.sessionCreated.then(function () {
                    model.on("audio", this.publishAudio.bind(this)), model.on("video", this.publishVideo.bind(this)), model.on("change:published", function (model, published) {
                        published && this.createPublisher()
                    }.bind(this)), model.trigger("subscribed"), this.sendTechStatus(), model.triggerChanges()
                }.bind(this))
            },
            publishAudio: function (publish) {
                this.publisher && this.publisher.publishAudio(!!publish)
            },
            publishVideo: function (publish) {
                this.publisher && this.publisher.publishVideo(!!publish)
            },
            getSessionID: function () {
                return this.config.webrtc ? this.config.webrtcSessionID : this.config.sessionID
            },
            createPublisher: function () {
                this.publisher || this.myStream.trigger("publisher:create", function () {
                    this.session && (this.publisher = this.session.publish("my-stream", {
                        publishVideo: this.myStream.hasVideo(),
                        publishAudio: this.myStream.hasAudio(),
                        width: 298,
                        height: 204,
                        style: {
                            buttonDisplayMode: "off"
                        }
                    }), this.publisher.on({
                        accessAllowed: this.accessAllowedHandler.bind(this),
                        accessDenied: this.accessDeniedHandler.bind(this),
                        accessDialogOpened: function (event) {
                            event.preventDefault()
                        }
                    }))
                }.bind(this))
            },
            accessAllowedHandler: function () {
                rollbar.log("accessAllowedHandler"), events.create(events.EVENT.LESSON_CHOOSE_AV_ACCESS, {
                    choice: "allow",
                    lessonCode: config.lessonCode
                }), this.add(this.myStream), this.myStream.trigger("access-allowed")
            },
            accessDeniedHandler: function (event) {
                event.preventDefault(), rollbar.log("accessDeniedHandler"), events.create(events.EVENT.LESSON_CHOOSE_AV_ACCESS, {
                    choice: "deny",
                    lessonCode: config.lessonCode
                }), this.myStream.trigger("access-denied")
            },
            registerStream: function () {
                if (!this.registering) {
                    this.registering = !0;
                    var ts = (new Date).getTime().toString();
                    util.API.post(config.CREATE_LESSON_EVENT_URL + "?_=" + ts, {
                        csrf: !0,
                        data: {
                            event: constants.LESSON_EVENT.STREAM,
                            connectionID: this.connectionID,
                            webrtc: this.config.webrtc ? 1 : 0
                        },
                        success: function (data) {
                            this.registerRetries = 0, this.myStream.register(), this.updateStreams(data)
                        }.bind(this),
                        error: function () {
                            rollbar.error("Failed to register stream"), ++this.registerRetries <= 5 && setTimeout(this.registerStream.bind(this), 1e3)
                        }.bind(this),
                        complete: function () {
                            this.registering = !1
                        }.bind(this)
                    })
                }
            },
            subscribeToStreams: function (streams) {
                _.each(streams, function (stream) {
                    var connectionID = stream.connection.connectionId;
                    if (!this.get(connectionID))
                        if (connectionID == this.connectionID) this.myStream.set({
                            stream: stream,
                            hasAudio: stream.hasAudio,
                            hasVideo: stream.hasVideo
                        }), this.myStream.updateID(connectionID);
                        else {
                            var model = new Stream({
                                user: config.otherUser
                            });
                            model.fetch({
                                id: connectionID,
                                stream: stream,
                                hasAudio: stream.hasAudio,
                                hasVideo: stream.hasVideo
                            }), this.add(model)
                        }
                    connectionID == this.connectionID && this.registerStream()
                }.bind(this))
            },
            updateStreams: function (data) {
                if (this.hasRequirements) {
                    data = data.opentok;
                    var studentConnectionID = this.config.webrtc ? data.studentWebRTCID : data.studentConnectionID,
                        tutorConnectionID = this.config.webrtc ? data.tutorWebRTCID : data.tutorConnectionID;
                    this.each(function (stream) {
                        stream.id && (stream.id == studentConnectionID || stream.id == tutorConnectionID ? stream.isRegistered() || stream.id == this.connectionID || (stream.register(), this.subscribeToOtherPartyStream(stream)) : stream.isRegistered() && (stream.id == this.connectionID ? this.registerStream() : this.remove(stream)))
                    }.bind(this))
                }
            },
            subscribeToOtherPartyStream: function (stream) {
                this.trigger("stream:subscribe", stream, function () {
                    try {
                        this.session.subscribe(stream.getStream(), "other-stream", {
                            width: 298,
                            height: 204
                        }), stream.hasVideo(stream.getStream().hasVideo), stream.hasAudio(stream.getStream().hasAudio), stream.trigger("subscribed")
                    } catch (err) {}
                }.bind(this))
            }
        });
    return {
        Stream: Stream,
        Opentok: Opentok
    }
}), define("session/video/views", ["session/managers", "session/audiobridge/views", "session/video/models", "session/models", "session/constants", "events", "browser", "config"], function (managers, lessonConferenceRegion, models, sessionModels, constants, events, Browser, config) {
    var Indicators = Backbone.Marionette.View.extend({
            ui: {
                audio: ".audio",
                video: ".video"
            },
            events: {
                "click .audio": "audioClicked",
                "click .video": "videoClicked"
            },
            modelEvents: {
                "change:hasAudio": "toggleAudio",
                "change:hasVideo": "toggleVideo"
            },
            initialize: function () {
                this.bindUIElements(), this.toggleAudio(), this.toggleVideo()
            },
            audioClicked: function () {
                this.trigger("indicator-clicked", "audio")
            },
            videoClicked: function () {
                this.trigger("indicator-clicked", "video")
            },
            toggleAudio: function () {
                var on = this.model.hasAudio();
                this.ui.audio[on ? "addClass" : "removeClass"]("on").prop("title", this.ui.audio.attr("data-title-" + (on ? "on" : "off")))
            },
            toggleVideo: function () {
                var on = this.model.hasVideo();
                this.ui.video[on ? "addClass" : "removeClass"]("on").prop("title", this.ui.video.attr("data-title-" + (on ? "on" : "off")))
            }
        }),
        HelpContainer = Backbone.Marionette.View.extend({
            TYPES: ["flash", "webrtc"],
            ui: {
                activateHelp: ".av-activate",
                techApproval: ".tech-approval",
                techPermissions: ".tech-permissions",
                techProblems: ".tech-problems",
                flashDowngrade: ".flash-downgrade"
            },
            events: {
                "click .activate": "publish",
                "click .show-tech-permissions": "showTechPermissions",
                "click .show-tech-approval": "showTechApproval",
                "click .show-tech-problems": "showTechProblems",
                "click .show-video-settings": "showVideoSettings"
            },
            modelEvents: {
                technology: "showTech",
                "access-allowed": "accessAllowed",
                "access-denied": "accessDenied",
                "publisher:create": "publisherCreated",
                "change:maximized": "maximized"
            },
            initialize: function () {
                this.bindUIElements(), this.ui.videoSettingsModal = $("#video-settings-modal"), this.addClass(Browser.getBrowser()).addClass(config.isDemoLesson ? "demo" : "standard"), this.tech = null
            },
            isVisible: function () {
                return this.$el.is(":visible")
            },
            addClass: function (className) {
                return this.$el.addClass(className), this.ui.videoSettingsModal.addClass(className), this
            },
            removeClass: function (className) {
                return this.$el.removeClass(className), this.ui.videoSettingsModal.removeClass(className), this
            },
            maximized: function () {
                this.model.isMaximized() && this.model.isPublished() && this.publish()
            },
            publish: function () {
                return this.ui.activateHelp.hide(), this.model.publish(), !1
            },
            showTech: function (type) {
                var oldTech = this.tech;
                this.tech = type, oldTech && this.tech != oldTech && this.showActivateHelp(), this.removeClass(this.TYPES.join(" ")).addClass(type)
            },
            hideAll: function () {
                _.each(this.ui, function ($el) {
                    $el.hide()
                })
            },
            accessAllowed: function () {
                this.hideAll(), this.$el.hide(), this.ui.videoSettingsModal.modal("hide"), "webrtc" != this.tech || this.model.viewedNote() || this.model.hasAudioOrVideo() || this.model.viewedNote(!1), this.trigger("show-stream-container")
            },
            accessDenied: function () {
                this.showTechPermissions()
            },
            publisherCreated: function () {
                this.ui.activateHelp.hide(), "webrtc" == this.tech ? (this.ui.techApproval.show(), Browser.isFirefox() && $("body").one("click", this.showTechPermissions.bind(this))) : this.accessAllowed()
            },
            showActivateHelp: function () {
                this.hideAll(), this.$el.show(), this.ui.activateHelp.show(), this.trigger("hide-stream-container")
            },
            showFlashDowngrade: function () {
                this.hideAll(), this.$el.show(), this.ui.flashDowngrade.show(), this.trigger("hide-stream-container")
            },
            showTechApproval: function () {
                this.hideAll(), this.ui.techApproval.show()
            },
            showTechPermissions: function () {
                this.hideAll(), this.ui.techPermissions.show()
            },
            showTechProblems: function () {
                this.hideAll(), this.ui.techProblems.show()
            },
            showVideoSettings: function () {
                this.ui.videoSettingsModal.modal("show")
            }
        }),
        Stream = Backbone.Marionette.View.extend({
            ui: {
                webrtcNote: ".webrtc-note",
                streamContainer: ".stream-container",
                minimize: ".minimize-stream",
                stream: "#other-stream"
            },
            events: {
                "click .minimize-stream": "userMinimize",
                "click .remove-note": "hideNote"
            },
            modelEvents: {
                "change:maximized": "resetContainer",
                "change:hasAudio": "checkAudio",
                "change:hasVideo": "checkVideo",
                "change:viewedNote": "toggleNote",
                subscribed: "setInitialState"
            },
            initialize: function (options) {
                this.streamID = _.ltrim(this.ui.stream, "#"), this.bindUIElements(), this.ui.maximize = options.$maximize, this.ui.maximize.on("click", this.maximize.bind(this)), this.indicators = new Indicators({
                    el: options.$indicators,
                    model: this.model
                })
            },
            setInitialState: function () {
                !this.model.isUserMinimized() && this.model.hasAudioOrVideo() ? this.maximize() : this.minimize(this.model.isUserMinimized())
            },
            resetContainer: function () {
                this.model.isMaximized() ? this.maximize() : this.minimize()
            },
            toggleNote: function () {
                this.model.viewedNote() ? this.hideNote() : this.ui.webrtcNote.show()
            },
            hideNote: function () {
                this.ui.webrtcNote.hide(), this.model.viewedNote(!0)
            },
            userMinimize: function () {
                this.minimize(!0)
            },
            minimize: function (manual) {
                this.$el.removeClass("maximized"), this.ui.minimize.hide(), manual && this.ui.maximize.show(), this.hideStream(), this.model.minimize(manual)
            },
            maximize: function () {
                this.$el.addClass("maximized"), this.ui.minimize.show(), this.ui.maximize.hide(), this.showStream(), this.model.maximize()
            },
            hideStream: function () {
                this.ui.stream.css({
                    visibility: "hidden",
                    height: 0
                })
            },
            showStream: function () {
                this.ui.stream.css({
                    visibility: "visible",
                    height: "204px"
                })
            },
            checkAudio: function () {
                this.model.hasAudio() && !this.model.isUserMinimized() ? this.maximize() : this.model.hasAudioOrVideo() || this.minimize(this.model.isUserMinimized())
            },
            checkVideo: function () {
                this.model.hasVideo() && !this.model.isUserMinimized() ? this.maximize() : this.model.hasAudioOrVideo() || this.minimize(this.model.isUserMinimized())
            },
            checkVideoElement: function (success) {
                $("#" + this.streamID).exists() || (this.ui.stream = $("<div>").prop("id", this.streamID), this.ui.streamContainer.append(this.ui.stream)), success && success()
            },
            getHeight: function () {
                return this.model.isMaximized() ? 204 : this.ui.maximize.is(":visible") ? 32 : 0
            }
        }),
        MyStream = Stream.extend({
            ui: {
                helpContainer: ".help-container",
                stream: "#my-stream",
                toggleVideo: ".toggle-video",
                toggleAudio: ".toggle-audio"
            },
            events: {
                "click .toggle-video": "toggleVideo",
                "click .toggle-audio": "toggleAudio"
            },
            modelEvents: {
                "access-allowed": "showButtons",
                "publisher:create": "checkVideoElement"
            },
            initialize: function (options) {
                Stream.prototype.initialize.call(this, options), this.accessAllowed = !1, this.helpContainer = new HelpContainer({
                    el: this.ui.helpContainer,
                    model: this.model
                }), this.helpContainer.on("show-stream-container", this.showStreamContainer.bind(this)), this.helpContainer.on("hide-stream-container", this.hideStreamContainer.bind(this)), this.listenTo(lessonConferenceRegion, "expandToggleView", this.userMinimize), this.listenTo(this.indicators, "indicator-clicked", this.indicatorClicked)
            },
            indicatorClicked: function (indicator) {
                if (this.model.isRegistered()) switch (indicator) {
                case "video":
                    this.toggleVideo();
                    break;
                case "audio":
                    this.toggleAudio()
                } else this.model.isMaximized() || this.toggleContainer()
            },
            showStreamContainer: function () {
                this.ui.streamContainer.addClass("visible"), this.showStream(), this.model.trigger("change")
            },
            maximize: function () {
                Stream.prototype.maximize.call(this), lessonConferenceRegion.hidden && lessonConferenceRegion.enabled && lessonConferenceRegion.display(), lessonConferenceRegion.forceHideContent()
            },
            hideStreamContainer: function () {
                this.ui.streamContainer.removeClass("visible"), this.model.trigger("change")
            },
            showStream: function () {
                this.accessAllowed ? Stream.prototype.showStream.call(this) : this.hideStream()
            },
            showButtons: function () {
                this.accessAllowed = !0, this.showStreamContainer(), this.ui.toggleVideo.show(), this.ui.toggleAudio.show()
            },
            setInitialState: function () {
                this.model.isMaximized() || config.lessonMedium != constants.LESSON_MEDIUM.TEXT && !this.model.isUserMinimized() ? this.maximize() : this.minimize(this.model.isUserMinimized())
            },
            toggleContainer: function () {
                this.model.isMaximized() ? this.minimize(!0) : this.maximize()
            },
            toggleVideo: function () {
                var desiredState = !this.model.hasVideo();
                events.create(events.EVENT.TOKBOX_VIDEO_TOGGLE, {
                    lessonCode: config.lessonCode,
                    on: desiredState
                }), this._toggleVideo(desiredState)
            },
            checkVideo: function () {
                this._toggleVideo(this.model.hasVideo())
            },
            _toggleVideo: function (hasVideo) {
                this.model.viewedNote(!0), hasVideo ? (this.model.enableVideo(), this.ui.toggleVideo.addClass("on"), this.ui.minimize.addClass("video-on")) : (this.model.disableVideo(), this.ui.toggleVideo.removeClass("on"), this.ui.minimize.removeClass("video-on"))
            },
            toggleAudio: function () {
                var desiredState = !this.model.hasAudio();
                events.create(events.EVENT.TOKBOX_AUDIO_TOGGLE, {
                    lessonCode: config.lessonCode,
                    on: desiredState
                }), this._toggleAudio(desiredState)
            },
            checkAudio: function () {
                this._toggleAudio(this.model.hasAudio())
            },
            _toggleAudio: function (hasAudio) {
                hasAudio ? (this.model.enableAudio(), this.ui.toggleAudio.addClass("on")) : (this.model.disableAudio(), this.ui.toggleAudio.removeClass("on"))
            },
            getHeight: function () {
                return this.model.isMaximized() && this.helpContainer.isVisible() ? 234 : Stream.prototype.getHeight.call(this)
            }
        }),
        StreamContainer = Backbone.Marionette.View.extend({
            ui: {
                videoBorder: "#video_border",
                chat: "#ta-widget",
                otherStreamContainer: "#other-stream-container"
            },
            collectionEvents: {
                "stream:created": "streamCreated",
                "stream:subscribe": "streamSubscribe"
            },
            initialize: function (options) {
                this.bindUIElements(), this.myStream = options.myStream, this.myStream.model.on("change", this.resizeWorkspace.bind(this))
            },
            streamCreated: function () {
                $("#audio-or-video-fail-button").disable()
            },
            streamSubscribe: function (stream, callback) {
                stream.on("change", this.resizeWorkspace.bind(this)), this.otherStream = new Stream({
                    el: this.ui.otherStreamContainer,
                    model: stream,
                    $maximize: $("#maximize-other-stream"),
                    $indicators: $(".other-av-indicators")
                }), this.otherStream.checkVideoElement(), callback()
            },
            chatRemoved: 0,
            resizeWorkspace: function () {
                var myStreamHeight = this.myStream.getHeight(),
                    otherStreamHeight = this.otherStream && this.otherStream.getHeight() || 0,
                    containerHeight = myStreamHeight + otherStreamHeight,
                    myStreamContainerTop = 57 + otherStreamHeight + this.$el.offset().top - 104;
                otherStreamHeight > 0 ? (this.myStream.ui.maximize.css("margin-bottom", 6), this.otherStream.model.isMaximized() ? this.myStream.model.isMaximized() && (myStreamContainerTop += 8, containerHeight += 8) : containerHeight -= otherStreamHeight) : this.myStream.ui.maximize.css("margin-bottom", 0);
                var removeFromChat = containerHeight;
                lessonConferenceRegion.$el.css("margin-top", 0), this.otherStream && this.otherStream.ui.maximize.is(":visible") && (removeFromChat += this.otherStream.getHeight(), this.myStream.model.isMaximized() && lessonConferenceRegion.$el.css("margin-top", 12)), this.myStream.model.isMaximized() || (containerHeight -= myStreamHeight), containerHeight > 0 && (removeFromChat += 6), removeFromChat -= this.chatRemoved, 0 !== removeFromChat && (managers.chatManager.updateHeight(removeFromChat), this.chatRemoved += removeFromChat), this.ui.videoBorder.css({
                    height: containerHeight
                }), this.myStream.$el.css({
                    left: 21,
                    top: myStreamContainerTop
                }), this.myStream.model.isMaximized() || this.otherStream && this.otherStream.model.isMaximized() ? this.ui.videoBorder.addClass("show") : this.ui.videoBorder.removeClass("show")
            },
            hideMyStream: function () {
                this.myStream.$el.hide()
            },
            showMyStream: function (enableAudioOrVideo) {
                enableAudioOrVideo ? this.myStream.$el.css({
                    top: 162,
                    left: "50%",
                    "margin-left": -148
                }).show() : this.myStream.$el.css({
                    "margin-left": "auto"
                }).show()
            },
            closeStream: function () {
                this.myStream.minimize(), this.collection.disconnect()
            }
        });
    return function () {
        var opentok = new models.Opentok,
            myStream = new models.Stream({
                user: config.lessonUser
            });
        myStream.fetch(), opentok.addMyStream(myStream);
        var myVideo = new MyStream({
                el: $("#my-stream-container"),
                model: myStream,
                $maximize: $("#maximize-my-stream"),
                $indicators: $(".my-av-indicators")
            }),
            container = new StreamContainer({
                el: $("#video_container"),
                collection: opentok,
                myStream: myVideo
            });
        return container
    }
}), define("profiles/edit", ["config", "util"], function (config, util) {
    $("#add-top-subject a").click(function () {
        $("#new-top-subject").slideDown(), $("#new-top-subject .pen-icon").click(), $("#subject-selector").chosen()
    });
    var editProfile, EditableProfileField = Backbone.Marionette.View.extend({
            ui: {
                textbox: ".inline-edit",
                penIcon: ".pen-icon",
                buttonSection: ".button-section",
                submitButton: ".button-submit",
                cancelButton: ".button-cancel",
                subject: ".subject-edit",
                deleteButton: ".button-delete"
            },
            events: {
                "click .pen-icon": "iconClick",
                "click .button-cancel": "cancelEdit",
                "click .button-submit": "submitEdit",
                "click .button-delete": "deleteEdit"
            },
            initialize: function (opts) {
                this.bindUIElements(), this.dataType = opts.dataType
            },
            lockOthers: function () {
                $(".pen-editable").attr("locked", !0), $(".pen-icon").removeClass("pen-active"), $(".pen-editable").css("opacity", "0.5"), $(".inline-edit-add-new").fadeOut(), $("#standardized-test-disabler").show()
            },
            unlockOthers: function () {
                $(".pen-editable").removeAttr("locked"), $(".pen-icon").addClass("pen-active"), $(".pen-editable").css("opacity", "1"), $(".inline-edit-add-new").fadeIn(), $("#standardized-test-disabler").hide()
            },
            isLocked: function () {
                return !!this.$el.attr("locked")
            },
            setLocked: function (locked) {
                locked ? this.$el.attr("locked", !0) : this.$el.removeAttr("locked").css("opacity", "1")
            },
            cancelEdit: function () {
                this.setEditable(!1), this.unlockOthers()
            },
            ajaxSuccess: function () {
                this.setEditable(!1), this.unlockOthers(), this.ui.submitButton.button("reset")
            },
            submitAjax: function (urlExt, titleIn, contentIn) {
                util.API.post("expert/update-" + urlExt + "/", {
                    csrf: !0,
                    data: {
                        title: titleIn,
                        content: contentIn
                    },
                    success: this.ajaxSuccess.bind(this),
                    error: function () {}
                })
            },
            submitEdit: function () {},
            deleteEdit: function () {},
            iconClick: function () {
                this.isLocked() || this.isEditable() || (this.lockOthers(), this.setEditable(!0), this.setLocked(!1))
            }
        }),
        EditableSchoolYearView = EditableProfileField.extend({
            ui: {
                yearEdit: ".year-edit",
                yearText: ".year-text-t",
                schoolEdit: ".school-edit",
                penIcon: ".pen-icon",
                buttonSection: ".button-section",
                submitButton: ".button-submit",
                cancelButton: ".button-cancel"
            },
            initialize: function (opts) {
                this.bindUIElements(), this.ui.yearEdit.hide(), this.dataType = opts.dataType
            },
            isEditable: function () {
                return !!this.ui.schoolEdit.attr("contenteditable")
            },
            setEditable: function (editable) {
                editable ? (this.ui.yearText.hide(), this.ui.yearEdit.show(), this.ui.schoolEdit.attr("contenteditable", !0), this.ui.buttonSection.addClass("active-buttons").slideDown(), this.valueBeforeEdit = this.ui.schoolEdit.text(), this.ui.schoolEdit.focus(), this.$el.css({
                    "background-color": "#f7f7f7",
                    border: "1px solid #bcbcbc"
                }), this.ui.schoolEdit.css("border", "1px solid #bcbcbc")) : (this.ui.yearText.text(this.ui.yearEdit.val()), this.ui.yearText.show(), this.ui.yearEdit.hide(), this.ui.schoolEdit.removeAttr("contenteditable"), this.ui.buttonSection.removeClass("active-buttons"), this.ui.buttonSection.slideUp(), this.$el.css({
                    "background-color": "white",
                    border: "none"
                }), this.ui.schoolEdit.css("border", "none"))
            },
            cancelEdit: function () {
                this.setEditable(!1), this.unlockOthers(), this.ui.schoolEdit.text(this.valueBeforeEdit)
            },
            ajaxSuccess: function () {
                this.setEditable(!1), this.unlockOthers(), this.ui.submitButton.button("reset")
            },
            submitEdit: function () {
                var trimmedText = _.trim(this.ui.schoolEdit.text());
                this.ui.submitButton.button("loading"), _.isBlank(trimmedText) ? this.ajaxSuccess() : this.submitAjax(this.dataType, trimmedText, this.ui.yearEdit.val())
            }
        }),
        EditableMajorView = EditableProfileField.extend({
            ui: {
                majorEdit: ".major-edit",
                penIcon: ".pen-icon",
                buttonSection: ".button-section",
                submitButton: ".button-submit",
                cancelButton: ".button-cancel"
            },
            initialize: function (opts) {
                this.bindUIElements(), this.dataType = opts.dataType
            },
            isEditable: function () {
                return !!this.ui.majorEdit.attr("contenteditable")
            },
            setEditable: function (editable) {
                editable ? (this.ui.majorEdit.attr("contenteditable", !0), this.ui.buttonSection.addClass("active-buttons").slideDown(), this.valueBeforeEdit = this.ui.majorEdit.text(), this.ui.majorEdit.focus(), this.$el.css({
                    "background-color": "#f7f7f7",
                    border: "1px solid #bcbcbc"
                }), this.ui.majorEdit.css("border", "1px solid #bcbcbc")) : (this.ui.majorEdit.removeAttr("contenteditable"), this.ui.buttonSection.removeClass("active-buttons"), this.ui.buttonSection.slideUp(), this.$el.css({
                    "background-color": "white",
                    border: "none"
                }), this.ui.majorEdit.css("border", "none"))
            },
            cancelEdit: function () {
                this.setEditable(!1), this.unlockOthers(), this.ui.majorEdit.text(this.valueBeforeEdit)
            },
            submitAjax: function (urlExt, titleIn) {
                util.API.post("expert/update-" + urlExt + "/", {
                    csrf: !0,
                    data: {
                        title: titleIn
                    },
                    success: this.ajaxSuccess.bind(this),
                    error: function () {}
                })
            },
            submitEdit: function () {
                var trimmedText = _.trim(this.ui.majorEdit.text());
                this.ui.submitButton.button("loading"), _.isBlank(trimmedText) ? this.ajaxSuccess() : this.submitAjax(this.dataType, trimmedText)
            }
        }),
        EditableSubjectFieldView = EditableProfileField.extend({
            initialize: function (opts) {
                this.bindUIElements(), this.valueBeforeEdit = "", this.isAddNewField = !!opts.isAddNewField, this.profileSection = opts.profileSection, this.isAddNewField && $("#new-subject-section").exists() && (this.ui.penIcon.css("visibility", "hidden"), this.template = _.template($("#new-subject-section").html())), this.dataType = opts.dataType
            },
            isEditable: function () {
                return !!this.ui.textbox.attr("contenteditable")
            },
            setEditable: function (editable) {
                editable ? (this.ui.textbox.attr("contenteditable", !0), this.ui.buttonSection.addClass("active-buttons").slideDown(), this.ui.deleteButton.slideDown(), this.valueBeforeEdit = this.ui.textbox.text(), this.$el.addClass("subject-active").removeClass("subject-inactive"), this.ui.textbox.focus()) : (this.ui.textbox.removeAttr("contenteditable"), this.ui.buttonSection.removeClass("active-buttons"), this.ui.deleteButton.slideUp(), this.ui.buttonSection.slideUp(), this.$el.addClass("subject-inactive").removeClass("subject-active"))
            },
            cancelEdit: function () {
                this.setEditable(!1), this.unlockOthers(), this.ui.textbox.text(this.valueBeforeEdit), this.isAddNewField && this.$el.slideUp()
            },
            quickAddHtmlTemplate: function (subject, sID, description) {
                var templateData = {
                    subject: subject,
                    sID: sID,
                    description: description
                };
                $("#new-top-subject-sep").after(this.template(templateData))
            },
            ajaxSuccess: function () {
                if (this.setEditable(!1), this.unlockOthers(), this.isAddNewField) {
                    var $subjectSelected = $("#subject-selector option:selected");
                    this.quickAddHtmlTemplate($("#subject-selector").val(), $subjectSelected.data("sid"), this.ui.textbox.text()), _.each($(".top-subject-field"), function (item) {
                        new EditableSubjectFieldView({
                            el: item,
                            dataType: "top-subject"
                        })
                    }), $subjectSelected.remove(), $("#subject-selector").trigger("liszt:updated"), this.ui.textbox.text(""), this.$el.slideUp()
                }
                this.ui.submitButton.button("reset"), "" === this.ui.textbox.text() && this.$el.slideUp()
            },
            submitEdit: function () {
                var trimmedText = _.trim(this.ui.textbox.text());
                _.isBlank(trimmedText) ? this.cancelEdit() : (this.ui.submitButton.button("loading"), "top-subject" == this.dataType ? this.submitAjax(this.dataType, this.ui.subject.data("sid") ? this.ui.subject.data("sid") : $("#subject-selector option:selected").data("sid"), trimmedText) : this.submitAjax(this.dataType, "0", trimmedText))
            },
            deleteEdit: function () {
                this.ui.textbox.text(""), this.submitAjax(this.dataType, this.ui.subject.data("sid") ? this.ui.subject.data("sid") : $("#subject-selector option:selected").data("sid"), "")
            }
        }),
        TimezoneView = Backbone.View.extend({
            events: {
                "change #id_region": "regionChangeHandler",
                "change #id_subregion": "subregionChangeHandler"
            },
            initialize: function (opts) {
                if (this.timezones = opts.timezones, this.$region = this.$("#id_region"), this.$region.chosen(), this.$subregion = this.$("#id_subregion"), this.$subregion.chosen(), this.$timezone = this.$("#id_timezone"), !config.timezone) {
                    var tz = window.jstz.determine().name();
                    this.$timezone.val(tz)
                }
                if (this.$timezone.val()) {
                    var timezoneParts = this.$timezone.val().split("/"),
                        region = _.first(timezoneParts),
                        subregion = _.rest(timezoneParts).join("/");
                    this.$region.val(region).trigger("liszt:updated"), this.setSubregionOptions(region, this.timezones[region].sort()), this.$subregion.val(subregion).trigger("liszt:updated")
                }
            },
            regionChangeHandler: function () {
                var region = this.$region.val();
                region ? this.setSubregionOptions(region, this.timezones[region].sort()) : this.setSubregionOptions(region, []), this.setTimezone(region, this.$subregion.val())
            },
            subregionChangeHandler: function () {
                this.setTimezone(this.$region.val(), this.$subregion.val())
            },
            setSubregionOptions: function (region, subregions) {
                var optionEl, compacted = _.compact(subregions);
                this.$subregion.html($("<option />").prop("value", "").html("--------")), _.each(compacted, function (subregion) {
                    optionEl = $("<option />").prop("value", subregion).html(subregion.replace(/_/g, " ")), this.$subregion.append(optionEl)
                }, this), this.$subregion.prop("disabled", !compacted.length).trigger("liszt:updated")
            },
            setTimezone: function (region, subregion) {
                var tz = "";
                (region && subregion || !_.compact(this.timezones[region]).length) && (tz = region, subregion && (tz += "/" + subregion)), this.$timezone.prop("value", tz)
            }
        }),
        EditScoresView = Backbone.View.extend({
            events: {
                "click .standardized-test": "toggleTestScores",
                "keyup input[data-max-score]": "checkMaxScore",
                "click .btn-primary": "validateScores",
                "click .button-submit": "submitEdit",
                "click .button-cancel": "cancelEdit"
            },
            anySectionsExpanded: function () {
                return !!$(".expanded").length
            },
            lockOthers: function () {
                $(".pen-editable").attr("locked", !0).css("opacity", "0.5"), $(".pen-icon").removeClass("pen-active"), $(".inline-edit-add-new").fadeOut()
            },
            unlockOthers: function () {
                $(".pen-editable").removeAttr("locked").css("opacity", "1"), $(".pen-icon").addClass("pen-active"), $(".inline-edit-add-new").fadeIn()
            },
            toggleTestScores: function (event) {
                var $target = $(event.target).closest("li"),
                    $scores = $target.find(".standardized-test-scores");
                $target.hasClass("expanded") ? ($scores.hide(), $target.removeClass("expanded")) : ($scores.show(), this.lockOthers(), $target.addClass("expanded")), this.anySectionsExpanded() ? $(".standardized-test-info .button-section").slideDown() : this.cancelEdit()
            },
            _invalidMaxScore: function ($input) {
                var maxScore = $input.attr("data-max-score"),
                    score = $input.val();
                return !_.isBlank(score) && (!$.isNumeric(score) || parseInt(score) < 0 || parseInt(score) > parseInt(maxScore))
            },
            checkMaxScore: function (event) {
                var $input = $(event.target),
                    $controlGroup = $input.closest(".control-group");
                this._invalidMaxScore($input) ? $controlGroup.addClass("error") : $controlGroup.removeClass("error")
            },
            validateScores: function () {
                var stopSubmit = !1,
                    self = this;
                return this.$("input[data-max-score]").each(function () {
                    var $input = $(this),
                        $controlGroup = $input.closest(".control-group");
                    self._invalidMaxScore($input) ? ($input.focus(), $controlGroup.addClass("error"), stopSubmit = !0) : $controlGroup.removeClass("error")
                }), !stopSubmit
            },
            cancelEdit: function () {
                this.unlockOthers(), $(".expanded a").click(), $(".standardized-test-info .button-section").slideUp()
            },
            submitEdit: function () {
                if (this.unlockOthers(), this.validateScores()) {
                    var scores = {};
                    this.$(".control-group input").each(function () {
                        var $i = $(this);
                        scores[$i.attr("name")] = $i.val()
                    }), util.API.post("expert/update-standardized-test/", {
                        csrf: !0,
                        data: scores,
                        success: function () {
                            $(".expanded a").click(), $(".standardized-test-info .button-section").slideUp()
                        }
                    })
                }
            }
        }),
        setupStandardizedTests = function () {
            $("#top-subjects-form > div > input").change(function () {
                var $this = $(this),
                    $textarea = $this.parent().parent().children("span.input-container");
                return $this.is(":checked") ? $textarea.show() : $textarea.hide(), !1
            })
        };
    return {
        validateTestScores: function () {
            return editProfile.validateScores()
        },
        init: function (opts) {
            opts = opts || {}, setupStandardizedTests();
            var $form = opts.$form || $(".standardized-test-info");
            editProfile = new EditScoresView({
                el: $form
            }), opts.timezones && new TimezoneView({
                el: $("#timezone-field-container"),
                timezones: opts.timezones
            }), new EditableSubjectFieldView({
                el: $("#about-experience"),
                dataType: "about-experience"
            }), new EditableSubjectFieldView({
                el: $("#about-extracurricular"),
                dataType: "about-extracurricular"
            }), new EditableSubjectFieldView({
                el: $("#new-top-subject"),
                isAddNewField: !0,
                dataType: "top-subject"
            }), new EditableMajorView({
                el: $("#inline-edit-major"),
                dataType: "major"
            }), new EditableSchoolYearView({
                el: $("#inline-edit-school"),
                dataType: "school"
            }), _.each($(".top-subject-field"), function (item) {
                new EditableSubjectFieldView({
                    el: item,
                    dataType: "top-subject"
                })
            })
        },
        initInterview: function (opts) {
            opts = opts || {}, setupStandardizedTests();
            var $form = opts.$form || $(".standardized-test-info");
            editProfile = new EditScoresView({
                el: $form
            })
        }
    }
}), define("profiles/views", ["util"], function (util) {
    var ENDPOINTS = {
            "set-new-password": "set-new-password/"
        },
        NewPasswordForm = Backbone.View.extend({
            $form: null,
            options: null,
            events: {
                "submit form": "submitForm",
                "click .btn-primary": "submitForm"
            },
            initialize: function (options) {
                this.$form = this.$("form"), this.options = options || {}
            },
            show: function () {
                this.$el.modal("show")
            },
            submitForm: function (event) {
                util.API.formSubmit(this.$el, event, {
                    endpoint: ENDPOINTS["set-new-password"],
                    data: this.$form.serialize(),
                    redirects: !0,
                    ajaxOptions: this.options.ajaxOptions || {}
                })
            }
        });
    return {
        NewPasswordForm: NewPasswordForm
    }
}), define("questions/models", ["util"], function (util) {
    var Q_EVENT_TYPE = {
            ASK: 1,
            CLAIM: 2,
            UNCLAIM: 3
        },
        AttachmentModel = util.BaseModel.extend({
            defaults: {
                label: ""
            },
            getLabel: function () {
                return this.get("label")
            },
            getHash: function () {
                return String(window.CryptoJS.MD5(this.getLabel()))
            }
        }),
        Question = util.BaseModel.extend({
            claim: function (options) {
                options.data = {
                    type: Q_EVENT_TYPE.CLAIM,
                    onQuestionPage: options.onQuestionPage
                }, this.createEvent(options)
            },
            unclaim: function (options) {
                options.data = {
                    type: Q_EVENT_TYPE.UNCLAIM,
                    onQuestionPage: options.onQuestionPage
                }, this.createEvent(options)
            },
            createEvent: function (options) {
                var ts = (new Date).getTime().toString();
                util.API.post(this.get("eventEndpoint") + "?_=" + ts, _.extend({
                    csrf: !0,
                    error: function () {
                        window.showErrorCatchall()
                    }
                }, options))
            },
            addComment: function (options) {
                util.API.post(Question.ENDPOINTS["add-comment"], options)
            },
            cancel: function (options) {
                util.API.post(Question.ENDPOINTS.cancel, options)
            },
            addExplanation: function (options, $form) {
                this._attachmentSubmit(Question.ENDPOINTS["add-explanation"], options, $form)
            },
            askAndSignup: function (options, $form) {
                this._attachmentSubmit(Question.ENDPOINTS["ask-and-signup"], options, $form)
            },
            _attachmentSubmit: function (endpoint, options, $form) {
                var opts = _.extend(options, {
                    dataType: "json",
                    ajaxCall: $form.ajaxSubmit.bind($form)
                });
                delete opts.data, util.API.post(endpoint, options)
            }
        });
    return Question.ENDPOINTS = {}, {
        Question: Question,
        AttachmentModel: AttachmentModel,
        EVENT_TYPES: {
            QUESTION: Q_EVENT_TYPE
        },
        setEndpoints: function (endpoints) {
            Question.ENDPOINTS = _.isObject(endpoints) ? endpoints : {}
        }
    }
}), define("questions/views", ["questions/models", "profiles/views", "experts/views", "schedule/views", "heartbeat", "config", "socket", "util"], function (models, profiles, experts, scheduling, heartbeat, config, socket, util) {
    var getSelectedRecipient = function ($select) {
            var val = $select.val();
            return {
                val: val,
                name: val ? $select.find(":selected").html() : ""
            }
        },
        QuestionView = Backbone.View.extend({
            $questionButtons: null,
            $unclaimModal: null,
            events: {
                "click .claim": "claimQuestion"
            },
            initialize: function () {
                this.model = new models.Question({
                    eventEndpoint: this.$el.attr("data-event-endpoint")
                })
            },
            claimQuestion: function () {
                return this.model.claim({
                    success: function (data) {
                        location.href = data.questionURL
                    },
                    onQuestionPage: !1
                }), !1
            }
        }),
        _updateAttachments = function (containerID, fileInputEvent) {
            var $container = $(containerID),
                $fileList = $container.find(".selected-files"),
                $uploadInput = $container.find("#fileupload"),
                $uploadInputContainer = $container.find(".btn-file"),
                $excludedFilesNames = $container.find("input[name=excluded_files]"),
                files = fileInputEvent.target.files;
            _.each(files, function (file) {
                var attachment = new models.AttachmentModel({
                        label: file.name
                    }),
                    fileView = new AttachmentRowPartialView({
                        model: attachment
                    }),
                    nameHash = attachment.getHash();
                $excludedFilesNames.val().indexOf(nameHash) > -1 && $excludedFilesNames.val($excludedFilesNames.val().replace("," + nameHash, "")), fileView.on("delete", function () {
                    $excludedFilesNames.val(function (_, val) {
                        return val + "," + nameHash
                    })
                }), fileView.render(), $fileList.append(fileView.el).hide().fadeIn().slideDown()
            }), $uploadInput.removeAttr("id"), $uploadInput.hide(), $uploadInputContainer.append('<input type="file" name="files" id="fileupload" multiple="">')
        },
        ExplanationFormView = QuestionView.extend({
            $explanation: null,
            $attachmentModal: null,
            initialize: function () {
                QuestionView.prototype.initialize.call(this), _.extend(this.events, {
                    "click .unclaim": "showUnclaimModal",
                    "click #submit-modal-submit": "submitExplanation",
                    "click input[type=submit]": "showSubmitModal",
                    "change #fileupload": "updateSelectedFiles"
                }), this.$questionButtons = this.$(".question-buttons"), this.$explanation = this.$("#explanation-form").closest(".row"), this.setup()
            },
            setup: function () {
                this.$attachmentModal = $("#bad-attachment-modal");
                var $explanationTimer = $("#explanation-timer");
                $explanationTimer.exists() && (this.timer = new util.DiffTimerView({
                    el: $explanationTimer,
                    endCallback: this.autoUnclaim.bind(this)
                })), this.$explanation.length > 0 && heartbeat.setBusy(!0), $("#explanation-form").ajaxForm()
            },
            claimQuestion: function () {
                return this.$questionButtons.find(".claim").prop("disabled", !0), this.model.claim({
                    onQuestionPage: !0,
                    success: function (data) {
                        0 === this.$explanation.length && (this.$explanation = $(data.content), this.$el.append(this.$explanation), this.setup()), this.$questionButtons.hide(), this.$explanation.show()
                    }.bind(this),
                    error: function (data, xhr) {
                        403 == xhr.status && $("#already-claimed-modal").modal("show")
                    }
                }), !1
            },
            showUnclaimModal: function () {
                return this.$unclaimModal || (this.$unclaimModal = $("#unclaim-modal"), this.$unclaimModal.find(".btn-primary").on("click", this.unclaimQuestion.bind(this))), this.$unclaimModal.show().modal("show"), !1
            },
            showSubmitModal: function (event) {
                return event.preventDefault(), this.$submitModal || (this.$submitModal = $("#submit-explanation-modal")), this.$submitModal.modal("show"), !1
            },
            unclaimQuestion: function () {
                var $btn = this.$unclaimModal.find(".btn-primary").button("loading");
                return this.model.unclaim({
                    success: function () {
                        this.finishExplanation(), location.href = models.Question.ENDPOINTS["open-questions"]
                    }.bind(this),
                    complete: function () {
                        $btn.button("reset")
                    }
                }), !1
            },
            updateSelectedFiles: function (event) {
                _updateAttachments("#explanation-form", event)
            },
            autoUnclaim: function () {
                this.model.unclaim({
                    auto: !0,
                    success: function () {
                        this.finishExplanation(), $("#auto-unclaim-modal").modal("show")
                    }.bind(this)
                })
            },
            submitExplanation: function (event) {
                return util.API.formSubmit($("#explanation-form"), event, {
                    callback: this.model.addExplanation.bind(this.model),
                    $btn: $(event.target),
                    ajaxOptions: {
                        success: function (data) {
                            this.finishExplanation(), data.facebookAutoshare ? window.facebookOgShareExplanation(data.redirect) : location.href = data.redirect
                        }.bind(this),
                        error: function (data) {
                            data.errors && "attachment" in data.errors && this.$attachmentModal.modal("show")
                        }.bind(this)
                    }
                }), !1
            },
            finishExplanation: function () {
                heartbeat.setBusy(!1)
            }
        }),
        ExplanationReviewForm = Backbone.View.extend({
            ENDPOINTS: {},
            $form: null,
            submitted: !1,
            positiveReview: !1,
            events: {
                "click .thumbs-up": "submitPositiveReview",
                "click .thumbs-down": "showNegativeReviewForm",
                "click .skip-review": "submitReviewSkip",
                "click .btn-primary": "submitReview"
            },
            initialize: function () {
                this.ENDPOINTS = {
                    "create-event": this.$el.attr("data-id") + "add-review/",
                    feedback: this.$el.attr("data-id") + "review/"
                }, this.$form = this.$("form")
            },
            showNegativeReviewForm: function (event) {
                this.positiveReview = !1, this.$(".label-thumbs-down").show(), this.showReviewForm(event)
            },
            showReviewForm: function (event) {
                event.preventDefault(), this.$form.show()
            },
            submitPositiveReview: function (event) {
                this.positiveReview = !0, this.submitReview(event)
            },
            submitReviewSkip: function (event) {
                this.$form.find("textarea").val(""), this.submitReview(event)
            },
            submitReview: function (event) {
                return event.preventDefault(), this.$form.hide(), this.submitted ? !1 : (this.submitted = !0, util.API.post(this.ENDPOINTS["create-event"], {
                    data: {
                        is_helpful: this.positiveReview,
                        text: this.$form.find("textarea").val()
                    },
                    csrf: !0,
                    success: function () {
                        this.positiveReview ? this.$el.removeClass().html("<h3>Thanks for your feedback!</h3>") : location.href = this.ENDPOINTS.feedback
                    }.bind(this)
                }), void 0)
            }
        }),
        RecipientSubjectsView = function (opts) {
            this.$recipientSelect = opts.$recipientSelect, this.$subjectSelect = opts.$subjectSelect, this.tutorSubjectsURL = opts.tutorSubjectsURL, this.userID = opts.userID, this.$recipientSelect.change(this.updateSubjects.bind(this)), this.defaultSubjects = this.subjectDataFromSelect(this.$subjectSelect), this.subjectCache = {}, this.$recipientSelect.val() || (this.subjectCache[this.$recipientSelect.val()] = this.defaultSubjects), this.optionTemplate = _.template('<option value="<%= id %>"><%= name %></option>')
        };
    _.extend(RecipientSubjectsView.prototype, {
        subjectDataFromSelect: function ($select) {
            return _.chain($select.find("option")).map(function (opt) {
                return opt.value ? {
                    id: opt.value,
                    name: opt.innerHTML
                } : void 0
            }).compact().value()
        },
        updateSubjects: function () {
            var selected = this.$subjectSelect.val(),
                empty = this.$subjectSelect.find("option")[0];
            this.$subjectSelect.html(empty).prop("disabled", !0).trigger("liszt:updated"), this.fetchSubjects().done(function (data) {
                _.each(data.subjects, function (subject) {
                    this.$subjectSelect.append(this.optionTemplate(subject))
                }, this), this.$subjectSelect.val(selected).prop("disabled", !1).trigger("liszt:updated")
            }.bind(this))
        },
        getSelectedTutor: function () {
            return getSelectedRecipient(this.$recipientSelect)
        },
        fetchSubjects: function () {
            var tutor = this.getSelectedTutor();
            return tutor.val in this.subjectCache ? $.Deferred().resolve({
                subjects: this.subjectCache[tutor.val]
            }) : tutor.val ? $.ajax({
                url: this.tutorSubjectsURL,
                type: "POST",
                data: {
                    csrfmiddlewaretoken: config.CSRF_TOKEN,
                    studentID: this.userID,
                    tutorID: tutor.val
                }
            }).done(function (data) {
                this.subjectCache[tutor.val] = data.subjects
            }.bind(this)) : $.Deferred().resolve({
                subjects: this.defaultSubjects
            })
        }
    });
    var AttachmentRowPartialView = Backbone.Marionette.ItemView.extend({
            template: "#file-row-partial",
            events: {
                "click .remove": "handleRemove"
            },
            handleRemove: function (e) {
                e.preventDefault(), this.$el.fadeOut(this.remove.bind(this)), this.trigger("delete", this.model)
            }
        }),
        AskQuestionView = Backbone.Marionette.View.extend({
            events: {
                "click .btn-primary": "processQuestion",
                "change #id_recipient": "updateSubjects",
                "change #fileupload": "updateSelectedFiles"
            },
            ui: {
                subjectSelect: "#id_subject_keyword",
                recipientSelect: "#id_recipient"
            },
            initialize: function (options) {
                this.bindUIElements(), this.model = new models.Question, this.storedContent = null, this.$attachmentModal = $("#bad-attachment-modal"), this.ui.recipientSelect.chosen(), this.shortModal = new ShortQuestionModal({
                    el: $("#short-question-modal"),
                    submitCallback: this.processQuestion.bind(this)
                }), this.moreInfoModal = new MoreInfoModal({
                    el: $("#more-info-modal"),
                    recipientSubjectsView: new RecipientSubjectsView({
                        $recipientSelect: this.ui.recipientSelect,
                        $subjectSelect: this.ui.subjectSelect,
                        tutorSubjectsURL: options.tutorSubjectsURL,
                        userID: options.userID
                    }),
                    submitCallback: this.submitQuestion.bind(this)
                }), this.$el.ajaxForm(), this.ui.recipientSelect.change()
            },
            getSelectedTutor: function () {
                return getSelectedRecipient(this.ui.recipientSelect)
            },
            getSubjectValue: function () {
                return this.$('select[name="subject_keyword"]').val()
            },
            processQuestion: function (event, bypassMin) {
                var $questionInput = this.$("textarea"),
                    len = this.$("textarea").val().length,
                    questionError = $("#question-form-errors").empty().hide();
                return this.getSubjectValue() || questionError.append("<li>Please enter a subject.</li>").slideDown(150), 0 === len && (questionError.append("<li>Please provide a question you wish to have answered.</li>").slideDown(150), $questionInput.addClass("error").on("focus", function (e) {
                    $(e.currentTarget).removeClass("error")
                })), questionError.is(":empty") ? !bypassMin && 25 >= len ? (this.shortModal.show(), !1) : (this.moreInfoModal.show(this.getSubjectValue(), this.getSelectedTutor()), !1) : !1
            },
            updateSelectedFiles: function (event) {
                _updateAttachments("#question-form", event)
            },
            submitQuestion: function (event, data) {
                if (data) {
                    var $extra = this.$(".extra-fields").empty();
                    _.each(data, function (val, key) {
                        $extra.append($("<input />", {
                            type: "hidden",
                            name: key,
                            value: val
                        }))
                    })
                }
                util.API.formSubmit(this.$el, event, {
                    data: data,
                    callback: this.model.askAndSignup.bind(this.model),
                    ajaxOptions: {
                        success: function (data) {
                            this.el.reset();
                            var content = data.content || this.storedContent;
                            if (content) {
                                var $content = $(content);
                                $("body").append($content);
                                var form = new profiles.NewPasswordForm({
                                    el: $content,
                                    ajaxOptions: {
                                        success: function () {
                                            location.href = data.questionURL
                                        }
                                    }
                                });
                                form.show()
                            } else location.href = data.questionURL
                        }.bind(this),
                        error: function (data) {
                            return data.dueErrors ? (this.moreInfoModal.showErrors({
                                errors: data.dueErrors,
                                subjectVal: this.getSubjectValue(),
                                tutor: this.getSelectedTutor()
                            }), void 0) : (this.moreInfoModal.dismiss(), "redirectURL" in data ? location.href = data.redirectURL : data.errors && "attachment" in data.errors && (this.$attachmentModal.modal("show"), data.content && (this.storedContent = data.content)), void 0)
                        }.bind(this)
                    }
                })
            }
        }),
        ShortQuestionModal = Backbone.View.extend({
            events: {
                "click .btn": "dismiss",
                "click .submit-anyway": "submitQuestion"
            },
            initialize: function (options) {
                this.submitCallback = options.submitCallback
            },
            show: function () {
                this.$el.modal("show")
            },
            dismiss: function () {
                this.$el.modal("hide")
            },
            submitQuestion: function (event) {
                this.dismiss();
                var data = this.getData();
                return this.validate(data) && this.submitCallback(event, data), !1
            },
            validate: function () {
                return !0
            },
            getData: function () {
                return !0
            }
        }),
        MoreInfoModal = ShortQuestionModal.extend({
            optionTemplate: _.template('<option value="<%= value %>" <% if (selected) { %>selected<% } %>><%= name %></option>'),
            headerTemplate: _.template("Before we send this to <%= recipient %>..."),
            defaultDurations: [
                [5, "5 minutes"],
                [10, "10 minutes"],
                [15, "15 minutes"],
                [20, "20 minutes"],
                [30, "30 minutes"],
                [45, "45 minutes"],
                [60, "1 hour"],
                [90, "1.5 hours"],
                [120, "2 hours"]
            ],
            extraDurations: [
                [5, "5 minutes"],
                [10, "10 minutes"],
                [15, "15 minutes"],
                [20, "20 minutes"],
                [30, "30 minutes"],
                [45, "45 minutes"],
                [60, "1 hour"],
                [90, "1.5 hours"],
                [120, "2 hours"],
                [180, "3 hours"]
            ],
            events: {
                "click .btn-primary": "submitQuestion"
            },
            initialize: function (options) {
                ShortQuestionModal.prototype.initialize.call(this, options), options.recipientSubjectsView || new RecipientSubjectsView({
                    $recipientSelect: this.$("#id_recipient"),
                    $subjectSelect: this.$("#id_subject_keyword"),
                    tutorSubjectsURL: options.tutorSubjectsURL,
                    userID: options.userID
                }), this.$durationSelect = this.$(".proposed-duration select"), this.$recipient = this.$("#id_recipient"), this.$recipient.chosen(), this.$header = this.$(".modal-header h2")
            },
            setupDateTooSoonModal: function (subject, recipient) {
                this.dateTooSoonModal || (this.dateTooSoonModal = new DateTooSoonModal({
                    el: $("#date-too-soon-modal"),
                    view: this
                })), this.dateTooSoonModal.setRecipient(recipient), this.dateTooSoonModal.setSubject(subject)
            },
            getSelectedTutor: function () {
                return getSelectedRecipient(this.$recipient)
            },
            show: function (subject, recipient) {
                this.$header.html(this.headerTemplate({
                    recipient: recipient.name.split(" ")[0] || "our tutors"
                })), this.setDurations(!!recipient.val), this.$el.modal("show"), this.setupDateTooSoonModal(subject, recipient), this.updateDateWidgets()
            },
            updateDateWidgets: function () {
                var time = util.getMinTime(),
                    dayDate = time.getDate(),
                    nextDayTimeTreshold = 18;
                time.getHours() > nextDayTimeTreshold && time.setDate(dayDate + 1), this.$(".datepicker").val(window.moment(time).format("MM/DD/YYYY")).datepicker({
                    dateFormat: "m/d/yy",
                    minDate: time.getHours() > nextDayTimeTreshold ? 1 : 0,
                    maxDate: "+3M"
                }), this.$(".timepicker").timepicker({
                    forceRoundTime: !0,
                    step: 60,
                    appendTo: this.$el,
                    minTime: "1:00am",
                    maxTime: "11:00pm",
                    endOption: {
                        label: "End of Day",
                        value: "End of Day"
                    }
                }).val("End of Day").timepicker("setTime", "End of Day")
            },
            setDurations: function (hasRecipient) {
                var val = this.$durationSelect.val(),
                    durations = hasRecipient ? this.extraDurations : this.defaultDurations;
                this.$durationSelect.empty(), _.each(durations, function (d) {
                    var value = d[0],
                        name = d[1],
                        selected = value.toString() === val;
                    this.$durationSelect.append(this.optionTemplate({
                        value: value,
                        name: name,
                        selected: selected
                    }))
                }, this)
            },
            validate: function (data) {
                var timeAllowed = 30 + parseInt(data.duration, 10),
                    diffMinutes = (new window.XDate).diffMinutes(new window.XDate(data.due_date)),
                    timeDiff = diffMinutes - timeAllowed;
                return 0 > timeDiff && diffMinutes > 0 ? (this.dateTooSoonModal.show(timeDiff), !1) : !0
            },
            getData: function () {
                var formData = this.$("form").serializeHash(),
                    timeString = util.getDatetimeString(this.$(".datepicker"), this.$(".timepicker"));
                return {
                    due_date: timeString,
                    duration: formData.duration
                }
            },
            showErrors: function (opts) {
                var errors = opts.errors,
                    subjectVal = opts.subjectVal,
                    tutor = opts.tutor;
                this.$(".form-error").empty(), _.each(errors, function (errors, name) {
                    var $ul = $("." + name + "-error");
                    _.each(errors, function (error) {
                        $ul.append($("<li/>").html(error))
                    }), $ul.show()
                }), this.show(subjectVal, tutor)
            }
        }),
        DateTooSoonModal = ShortQuestionModal.extend({
            events: {
                "click .btn-primary": "findFastestMatch",
                "click .show-more-info-modal": "showMoreInfoModal"
            },
            show: function (timeDiff) {
                Math.abs(timeDiff) >= 3600 && (this.$(".two-hours").show(), this.$(".one-hour").hide()), ShortQuestionModal.prototype.show.call(this)
            },
            initialize: function (options) {
                this.view = options.view
            },
            setSubject: function (subject) {
                subject && (this.subject = subject)
            },
            setRecipient: function (recipient) {
                this.recipient = recipient
            },
            findFastestMatch: function (event) {
                this.subject || (window.location.href = "/"), util.API.formSubmit(this.$el, event, {
                    endpoint: "subjects/get-help-page/",
                    data: {
                        subject: this.subject
                    },
                    redirects: !0,
                    ajaxOptions: {
                        success: function (data) {
                            window.location.href = data.nextURL
                        }
                    }
                })
            },
            showMoreInfoModal: function () {
                this.dismiss(), this.view.show(this.subject, this.recipient)
            }
        }),
        CommentForm = Backbone.View.extend({
            $comments: null,
            $reply: null,
            $expandComments: null,
            $expandLink: null,
            $form: null,
            $textarea: null,
            events: {
                "click .expand-comments": "expandCommentBox",
                "click .expand-reply": "expandReplyBox",
                "click .btn-primary": "submitComment"
            },
            initialize: function () {
                this.$comments = this.$(".comments"), this.$reply = this.$(".reply"), this.$expandComments = this.$(".expand-comments"), this.$expandLink = this.$(".expand-link"), this.$expandReply = this.$(".expand-reply"), this.$form = this.$("form"), this.$textarea = this.$("textarea")
            },
            expandCommentBox: function () {
                return this.$comments.toggle(), this.$comments.is(":visible") ? (this.$expandComments.addClass("expanded"), this.$textarea.focus()) : this.$expandComments.removeClass("expanded"), !1
            },
            expandReplyBox: function () {
                this.$reply.toggle();
                var expandText = this.$expandReply.text();
                return this.$reply.is(":visible") ? (this.$expandReply.text(expandText.replace("+", "-")), this.$textarea.focus()) : this.$expandReply.text(expandText.replace("-", "+")), !1
            },
            submitComment: function (event) {
                var model = new models.Question;
                util.API.formSubmit(this.$form, event, {
                    callback: model.addComment.bind(model),
                    ajaxOptions: {
                        csrf: !0,
                        success: function (data) {
                            if (this.$form[0].reset(), data.content) {
                                var $el = this.$expandLink.length > 0 ? this.$expandLink : this.$reply;
                                $el.before(data.content)
                            }
                            this.$textarea.val("").focus().blur(), this.$expandComments.hide(), this.$reply.hide(), this.$expandLink.show(), this.$("label").removeClass("red-label").text("Enter your comment here...")
                        }.bind(this)
                    }
                })
            }
        });
    return {
        QuestionView: QuestionView,
        ExplanationFormView: ExplanationFormView,
        AskQuestionView: AskQuestionView,
        ExplanationReviewForm: ExplanationReviewForm,
        MoreInfoModal: MoreInfoModal,
        DateTooSoonModal: DateTooSoonModal,
        initAnswerPage: function (messageEndpoints) {
            $(".review").not("[data-reviewed]").each(function () {
                new ExplanationReviewForm({
                    el: $(this)
                })
            }), new CommentForm({
                el: $(".comments-container")
            }), $(".message-form").each(function () {
                new experts.MessageForm({
                    el: $(this),
                    ENDPOINTS: messageEndpoints
                })
            }), scheduling.setupSchedulingSidebar(), $(".chosen-container select").chosen()
        }
    }
});